mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #10415 from kinglozzer/10413-php81-enums
NEW: Add support for autoloading PHP 8.1 enums
This commit is contained in:
commit
1253ab82af
@ -31,7 +31,7 @@
|
||||
"league/csv": "^8 || ^9",
|
||||
"m1/env": "^2.1",
|
||||
"monolog/monolog": "^1.16",
|
||||
"nikic/php-parser": "^3 || ^4",
|
||||
"nikic/php-parser": "^4.10.5",
|
||||
"psr/container": "^1",
|
||||
"silverstripe/config": "^1@dev",
|
||||
"silverstripe/assets": "^1@dev",
|
||||
|
@ -6,7 +6,7 @@ namespace SilverStripe\Core\Manifest;
|
||||
* Class ClassContentRemover
|
||||
* @package SilverStripe\Core\Manifest
|
||||
*
|
||||
* A utility class to clean the contents of a PHP file containing classes.
|
||||
* A utility class to clean the contents of a PHP file containing classes/interfaces/traits/enums.
|
||||
*
|
||||
* It removes any code with in `$cut_off_depth` number of curly braces.
|
||||
*/
|
||||
@ -29,7 +29,7 @@ class ClassContentRemover
|
||||
return $contents;
|
||||
}
|
||||
|
||||
if (!preg_match('/\b(?:class|interface|trait)/i', $contents ?? '')) {
|
||||
if (!preg_match('/\b(?:class|interface|trait|enum)/i', $contents ?? '')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
@ -50,7 +50,12 @@ class ClassContentRemover
|
||||
}
|
||||
|
||||
// only count if we see a class/interface/trait keyword
|
||||
if (!$startCounting && in_array($token[0], [T_CLASS, T_INTERFACE, T_TRAIT])) {
|
||||
$targetTokens = [T_CLASS, T_INTERFACE, T_TRAIT];
|
||||
if (version_compare(phpversion(), '8.1.0', '>')) {
|
||||
$targetTokens[] = T_ENUM;
|
||||
}
|
||||
|
||||
if (!$startCounting && in_array($token[0], $targetTokens)) {
|
||||
$startCounting = true;
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,8 @@ class ClassManifest
|
||||
'implementors',
|
||||
'traits',
|
||||
'traitNames',
|
||||
'enums',
|
||||
'enumNames',
|
||||
];
|
||||
|
||||
/**
|
||||
@ -150,6 +152,20 @@ class ClassManifest
|
||||
*/
|
||||
protected $traitNames = [];
|
||||
|
||||
/**
|
||||
* Map of lowercase enum names to paths
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $enums = [];
|
||||
|
||||
/**
|
||||
* Map of lowercase enum names to proper case
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $enumNames = [];
|
||||
|
||||
/**
|
||||
* PHP Parser for parsing found files
|
||||
*
|
||||
@ -334,10 +350,11 @@ class ClassManifest
|
||||
{
|
||||
$lowerName = strtolower($name ?? '');
|
||||
foreach ([
|
||||
$this->classes,
|
||||
$this->interfaces,
|
||||
$this->traits,
|
||||
] as $source) {
|
||||
$this->classes,
|
||||
$this->interfaces,
|
||||
$this->traits,
|
||||
$this->enums,
|
||||
] as $source) {
|
||||
if (isset($source[$lowerName]) && file_exists($source[$lowerName] ?? '')) {
|
||||
return $source[$lowerName];
|
||||
}
|
||||
@ -355,10 +372,11 @@ class ClassManifest
|
||||
{
|
||||
$lowerName = strtolower($name ?? '');
|
||||
foreach ([
|
||||
$this->classNames,
|
||||
$this->interfaceNames,
|
||||
$this->traitNames,
|
||||
] as $source) {
|
||||
$this->classNames,
|
||||
$this->interfaceNames,
|
||||
$this->traitNames,
|
||||
$this->enumNames,
|
||||
] as $source) {
|
||||
if (isset($source[$lowerName])) {
|
||||
return $source[$lowerName];
|
||||
}
|
||||
@ -406,6 +424,26 @@ class ClassManifest
|
||||
return $this->traitNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of lowercased enum names to file paths.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getEnums()
|
||||
{
|
||||
return $this->enums;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of lowercase enum names to proper enum names in the manifest
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getEnumNames()
|
||||
{
|
||||
return $this->enumNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all the descendant data.
|
||||
*
|
||||
@ -562,6 +600,7 @@ class ClassManifest
|
||||
$classes = $data['classes'];
|
||||
$interfaces = $data['interfaces'];
|
||||
$traits = $data['traits'];
|
||||
$enums = $data['enums'];
|
||||
} else {
|
||||
$changed = true;
|
||||
// Build from php file parser
|
||||
@ -579,6 +618,7 @@ class ClassManifest
|
||||
$classes = $this->getVisitor()->getClasses();
|
||||
$interfaces = $this->getVisitor()->getInterfaces();
|
||||
$traits = $this->getVisitor()->getTraits();
|
||||
$enums = $this->getVisitor()->getEnums();
|
||||
}
|
||||
|
||||
// Merge raw class data into global list
|
||||
@ -641,6 +681,13 @@ class ClassManifest
|
||||
$this->traitNames[$lowerTrait] = $traitName;
|
||||
}
|
||||
|
||||
// Merge all enums
|
||||
foreach ($enums as $enumName => $enumInfo) {
|
||||
$lowerEnum = strtolower($enumName ?? '');
|
||||
$this->enums[$lowerEnum] = $pathname;
|
||||
$this->enumNames[$lowerEnum] = $enumName;
|
||||
}
|
||||
|
||||
// Save back to cache if configured
|
||||
if ($changed && $this->cache) {
|
||||
$cache = [
|
||||
@ -725,7 +772,7 @@ class ClassManifest
|
||||
if (!$data || !is_array($data)) {
|
||||
return false;
|
||||
}
|
||||
foreach (['classes', 'interfaces', 'traits'] as $key) {
|
||||
foreach (['classes', 'interfaces', 'traits', 'enums'] as $key) {
|
||||
// Must be set
|
||||
if (!isset($data[$key])) {
|
||||
return false;
|
||||
|
@ -15,10 +15,20 @@ class ClassManifestVisitor extends NodeVisitorAbstract
|
||||
|
||||
private $interfaces = [];
|
||||
|
||||
private bool $includeEnums;
|
||||
|
||||
private $enums = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->includeEnums = version_compare(phpversion(), '8.1.0', '>');
|
||||
}
|
||||
|
||||
public function resetState()
|
||||
{
|
||||
$this->classes = [];
|
||||
$this->traits = [];
|
||||
$this->enums = [];
|
||||
$this->interfaces = [];
|
||||
}
|
||||
|
||||
@ -49,6 +59,8 @@ class ClassManifestVisitor extends NodeVisitorAbstract
|
||||
];
|
||||
} elseif ($node instanceof Node\Stmt\Trait_) {
|
||||
$this->traits[(string)$node->namespacedName] = [];
|
||||
} elseif ($this->includeEnums && $node instanceof Node\Stmt\Enum_) {
|
||||
$this->enums[(string)$node->namespacedName] = [];
|
||||
} elseif ($node instanceof Node\Stmt\Interface_) {
|
||||
$extends = [];
|
||||
foreach ($node->extends as $ancestor) {
|
||||
@ -74,6 +86,11 @@ class ClassManifestVisitor extends NodeVisitorAbstract
|
||||
return $this->traits;
|
||||
}
|
||||
|
||||
public function getEnums()
|
||||
{
|
||||
return $this->enums;
|
||||
}
|
||||
|
||||
public function getInterfaces()
|
||||
{
|
||||
return $this->interfaces;
|
||||
|
@ -43,7 +43,7 @@ class ClassManifestTest extends SapphireTest
|
||||
*/
|
||||
public function providerTestGetItemPath()
|
||||
{
|
||||
return [
|
||||
$paths = [
|
||||
['CLASSA', 'module/classes/ClassA.php'],
|
||||
['ClassA', 'module/classes/ClassA.php'],
|
||||
['classa', 'module/classes/ClassA.php'],
|
||||
@ -55,6 +55,14 @@ class ClassManifestTest extends SapphireTest
|
||||
['VendorClassA', 'vendor/silverstripe/modulec/code/VendorClassA.php'],
|
||||
['VendorTraitA', 'vendor/silverstripe/modulec/code/VendorTraitA.php'],
|
||||
];
|
||||
|
||||
if (version_compare(phpversion(), '8.1.0', '>')) {
|
||||
$paths[] = ['ENUMA', 'module/enums/EnumA.php'];
|
||||
$paths[] = ['EnumA', 'module/enums/EnumA.php'];
|
||||
$paths[] = ['enuma', 'module/enums/EnumA.php'];
|
||||
}
|
||||
|
||||
return $paths;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,6 +177,34 @@ class ClassManifestTest extends SapphireTest
|
||||
}
|
||||
}
|
||||
|
||||
public function testGetEnums()
|
||||
{
|
||||
if (!version_compare(phpversion(), '8.1.0', '>')) {
|
||||
$this->markTestSkipped('Enums are only available on PHP 8.1+');
|
||||
}
|
||||
|
||||
$expect = [
|
||||
'enuma' => "{$this->base}/module/enums/EnumA.php",
|
||||
'enumb' => "{$this->base}/module/enums/EnumB.php",
|
||||
];
|
||||
$this->assertEquals($expect, $this->manifest->getEnums());
|
||||
}
|
||||
|
||||
public function testGetEnumNames()
|
||||
{
|
||||
if (!version_compare(phpversion(), '8.1.0', '>')) {
|
||||
$this->markTestSkipped('Enums are only available on PHP 8.1+');
|
||||
}
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
'enuma' => 'EnumA',
|
||||
'enumb' => 'EnumB',
|
||||
],
|
||||
$this->manifest->getEnumNames()
|
||||
);
|
||||
}
|
||||
|
||||
public function testTestManifestIncludesTestClasses()
|
||||
{
|
||||
$this->assertArrayNotHasKey('testclassa', $this->manifest->getClasses());
|
||||
|
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
enum EnumA { }
|
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
enum EnumB { }
|
Loading…
Reference in New Issue
Block a user