silverstripe-framework: ClassManifest picks up classes that won't exists because of `class_exists` statements
Affected Version
^4.0
Description
Sometimes you have classes that will only conditionally exists if another class exists. This is helpful when you’re implementing a feature that will only be available if another module is installed.
Only problem is that because ClassManifest
uses static code analysis to decide what classes exists it won’t pick up if there’s a statement like this at the start of the file.
if (!class_exists(RegistryPage::class)) {
return;
}
Steps to Reproduce
Create a file with this code.
<?php
use SilverStripe\Core\ClassInfo;
use SilverStripe\Dev\BuildTask;
use SilverStripe\ORM\DataObject;
class TestBuild extends BuildTask {
public function run($request)
{
$subClasses = ClassInfo::subclassesFor(DataObject::class);
if (in_array('Test', $subClasses)) {
echo "Test is returned by subclassesFor\n";
} else {
echo "Test is NOT returned by subclassesFor\n";
}
}
}
if (!class_exists(NonExistant::class)) {
return;
}
class Test extends DataObject {
}
Expected outcome: When you run sake dev/tasks/TestBuild
, “Test is NOT returned by subclassesFor” should be outputted.
Actual outcome: When you run sake dev/tasks/TestBuild
, “Test is returned by subclassesFor” is outputted.
About this issue
- Original URL
- State: open
- Created 4 years ago
- Comments: 19 (19 by maintainers)
OK - I think we should get some core feedback on this (@silverstripe/core-team).
So, solutions I see - any other ideas and I can add them:
👍: Update the docs to make it clear that the manifest /
ClassInfo
may return classes that aren’t defined at runtime and it’s for the developer to check these ❤️: UpdateClassInfo
(orClassManifest
if appropriate) to useclass_exists()
calls to filter out classes that are not defined at runtime 🎉: UpdateClassManifest
to evaluate conditionals that appear to prevent definition of classes at runtimeYeah I would be inclined to keep ClassManifest as-is, but potentially add a class_exists filter to subclassesOf or maybe some of the places that call it.
I don’t think that fixing this by banning the use of load-time class_exists calls should be given too much consideration.