mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
NEW: Add support for autoloading PHP 8.1 enums
This commit is contained in:
parent
c0e8a21acf
commit
d3f104382d
@ -6,7 +6,7 @@ namespace SilverStripe\Core\Manifest;
|
|||||||
* Class ClassContentRemover
|
* Class ClassContentRemover
|
||||||
* @package SilverStripe\Core\Manifest
|
* @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.
|
* It removes any code with in `$cut_off_depth` number of curly braces.
|
||||||
*/
|
*/
|
||||||
@ -29,7 +29,7 @@ class ClassContentRemover
|
|||||||
return $contents;
|
return $contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!preg_match('/\b(?:class|interface|trait)/i', $contents ?? '')) {
|
if (!preg_match('/\b(?:class|interface|trait|enum)/i', $contents ?? '')) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +50,12 @@ class ClassContentRemover
|
|||||||
}
|
}
|
||||||
|
|
||||||
// only count if we see a class/interface/trait keyword
|
// 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;
|
$startCounting = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +67,8 @@ class ClassManifest
|
|||||||
'implementors',
|
'implementors',
|
||||||
'traits',
|
'traits',
|
||||||
'traitNames',
|
'traitNames',
|
||||||
|
'enums',
|
||||||
|
'enumNames',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -150,6 +152,20 @@ class ClassManifest
|
|||||||
*/
|
*/
|
||||||
protected $traitNames = [];
|
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
|
* PHP Parser for parsing found files
|
||||||
*
|
*
|
||||||
@ -334,10 +350,11 @@ class ClassManifest
|
|||||||
{
|
{
|
||||||
$lowerName = strtolower($name ?? '');
|
$lowerName = strtolower($name ?? '');
|
||||||
foreach ([
|
foreach ([
|
||||||
$this->classes,
|
$this->classes,
|
||||||
$this->interfaces,
|
$this->interfaces,
|
||||||
$this->traits,
|
$this->traits,
|
||||||
] as $source) {
|
$this->enums,
|
||||||
|
] as $source) {
|
||||||
if (isset($source[$lowerName]) && file_exists($source[$lowerName] ?? '')) {
|
if (isset($source[$lowerName]) && file_exists($source[$lowerName] ?? '')) {
|
||||||
return $source[$lowerName];
|
return $source[$lowerName];
|
||||||
}
|
}
|
||||||
@ -355,10 +372,11 @@ class ClassManifest
|
|||||||
{
|
{
|
||||||
$lowerName = strtolower($name ?? '');
|
$lowerName = strtolower($name ?? '');
|
||||||
foreach ([
|
foreach ([
|
||||||
$this->classNames,
|
$this->classNames,
|
||||||
$this->interfaceNames,
|
$this->interfaceNames,
|
||||||
$this->traitNames,
|
$this->traitNames,
|
||||||
] as $source) {
|
$this->enumNames,
|
||||||
|
] as $source) {
|
||||||
if (isset($source[$lowerName])) {
|
if (isset($source[$lowerName])) {
|
||||||
return $source[$lowerName];
|
return $source[$lowerName];
|
||||||
}
|
}
|
||||||
@ -406,6 +424,26 @@ class ClassManifest
|
|||||||
return $this->traitNames;
|
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.
|
* Returns an array of all the descendant data.
|
||||||
*
|
*
|
||||||
@ -562,6 +600,7 @@ class ClassManifest
|
|||||||
$classes = $data['classes'];
|
$classes = $data['classes'];
|
||||||
$interfaces = $data['interfaces'];
|
$interfaces = $data['interfaces'];
|
||||||
$traits = $data['traits'];
|
$traits = $data['traits'];
|
||||||
|
$enums = $data['enums'];
|
||||||
} else {
|
} else {
|
||||||
$changed = true;
|
$changed = true;
|
||||||
// Build from php file parser
|
// Build from php file parser
|
||||||
@ -579,6 +618,7 @@ class ClassManifest
|
|||||||
$classes = $this->getVisitor()->getClasses();
|
$classes = $this->getVisitor()->getClasses();
|
||||||
$interfaces = $this->getVisitor()->getInterfaces();
|
$interfaces = $this->getVisitor()->getInterfaces();
|
||||||
$traits = $this->getVisitor()->getTraits();
|
$traits = $this->getVisitor()->getTraits();
|
||||||
|
$enums = $this->getVisitor()->getEnums();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge raw class data into global list
|
// Merge raw class data into global list
|
||||||
@ -641,6 +681,13 @@ class ClassManifest
|
|||||||
$this->traitNames[$lowerTrait] = $traitName;
|
$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
|
// Save back to cache if configured
|
||||||
if ($changed && $this->cache) {
|
if ($changed && $this->cache) {
|
||||||
$cache = [
|
$cache = [
|
||||||
@ -725,7 +772,7 @@ class ClassManifest
|
|||||||
if (!$data || !is_array($data)) {
|
if (!$data || !is_array($data)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
foreach (['classes', 'interfaces', 'traits'] as $key) {
|
foreach (['classes', 'interfaces', 'traits', 'enums'] as $key) {
|
||||||
// Must be set
|
// Must be set
|
||||||
if (!isset($data[$key])) {
|
if (!isset($data[$key])) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -15,10 +15,20 @@ class ClassManifestVisitor extends NodeVisitorAbstract
|
|||||||
|
|
||||||
private $interfaces = [];
|
private $interfaces = [];
|
||||||
|
|
||||||
|
private bool $includeEnums;
|
||||||
|
|
||||||
|
private $enums = [];
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->includeEnums = version_compare(phpversion(), '8.1.0', '>');
|
||||||
|
}
|
||||||
|
|
||||||
public function resetState()
|
public function resetState()
|
||||||
{
|
{
|
||||||
$this->classes = [];
|
$this->classes = [];
|
||||||
$this->traits = [];
|
$this->traits = [];
|
||||||
|
$this->enums = [];
|
||||||
$this->interfaces = [];
|
$this->interfaces = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +59,8 @@ class ClassManifestVisitor extends NodeVisitorAbstract
|
|||||||
];
|
];
|
||||||
} elseif ($node instanceof Node\Stmt\Trait_) {
|
} elseif ($node instanceof Node\Stmt\Trait_) {
|
||||||
$this->traits[(string)$node->namespacedName] = [];
|
$this->traits[(string)$node->namespacedName] = [];
|
||||||
|
} elseif ($this->includeEnums && $node instanceof Node\Stmt\Enum_) {
|
||||||
|
$this->enums[(string)$node->namespacedName] = [];
|
||||||
} elseif ($node instanceof Node\Stmt\Interface_) {
|
} elseif ($node instanceof Node\Stmt\Interface_) {
|
||||||
$extends = [];
|
$extends = [];
|
||||||
foreach ($node->extends as $ancestor) {
|
foreach ($node->extends as $ancestor) {
|
||||||
@ -74,6 +86,11 @@ class ClassManifestVisitor extends NodeVisitorAbstract
|
|||||||
return $this->traits;
|
return $this->traits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getEnums()
|
||||||
|
{
|
||||||
|
return $this->enums;
|
||||||
|
}
|
||||||
|
|
||||||
public function getInterfaces()
|
public function getInterfaces()
|
||||||
{
|
{
|
||||||
return $this->interfaces;
|
return $this->interfaces;
|
||||||
|
@ -43,7 +43,7 @@ class ClassManifestTest extends SapphireTest
|
|||||||
*/
|
*/
|
||||||
public function providerTestGetItemPath()
|
public function providerTestGetItemPath()
|
||||||
{
|
{
|
||||||
return [
|
$paths = [
|
||||||
['CLASSA', 'module/classes/ClassA.php'],
|
['CLASSA', 'module/classes/ClassA.php'],
|
||||||
['ClassA', 'module/classes/ClassA.php'],
|
['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'],
|
['VendorClassA', 'vendor/silverstripe/modulec/code/VendorClassA.php'],
|
||||||
['VendorTraitA', 'vendor/silverstripe/modulec/code/VendorTraitA.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()
|
public function testTestManifestIncludesTestClasses()
|
||||||
{
|
{
|
||||||
$this->assertArrayNotHasKey('testclassa', $this->manifest->getClasses());
|
$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