From 4ad69508955c1b4b627822efabfdf8fca85cb478 Mon Sep 17 00:00:00 2001 From: Ruslan Kabalin Date: Thu, 26 Sep 2024 15:29:23 +0100 Subject: [PATCH] Adjust filter plugin requirements to comply with 4.5. Per https://moodledev.io/docs/4.5/devupdate#filter-plugins Fixes #321 --- src/Parser/StatementFilter.php | 22 +++++++++++ .../Finder/FunctionCallFinder.php | 37 ++++++++++++++++++ src/PluginValidate/PluginValidate.php | 2 + .../Requirements/AbstractRequirements.php | 7 ++++ .../Requirements/FilterRequirements.php | 28 +++++++++++-- .../Requirements/GenericRequirements.php | 5 +++ .../Requirements/FilterRequirementsTest.php | 39 +++++++++++++++---- 7 files changed, 128 insertions(+), 12 deletions(-) create mode 100644 src/PluginValidate/Finder/FunctionCallFinder.php diff --git a/src/Parser/StatementFilter.php b/src/Parser/StatementFilter.php index 04649de6..4d5bb4e2 100644 --- a/src/Parser/StatementFilter.php +++ b/src/Parser/StatementFilter.php @@ -14,9 +14,11 @@ use PhpParser\Node\Expr\Array_; use PhpParser\Node\Expr\Assign; +use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\PropertyFetch; use PhpParser\Node\Expr\Variable; use PhpParser\Node\Identifier; +use PhpParser\Node\Name; use PhpParser\Node\Scalar\String_; use PhpParser\Node\Stmt; use PhpParser\Node\Stmt\Class_; @@ -116,6 +118,26 @@ public function filterAssignments(array $statements): array return $assigns; } + /** + * Extract all the function call expressions from the statements. + * + * @param Stmt[] $statements + * + * @return FuncCall[] + */ + public function filterFunctionCalls(array $statements): array + { + $calls = []; + foreach ($statements as $statement) { + // Only expressions that are function calls. + if ($statement instanceof Expression && $statement->expr instanceof FuncCall) { + $calls[] = $statement->expr; + } + } + + return $calls; + } + /** * Find first variable assignment with a given name. * diff --git a/src/PluginValidate/Finder/FunctionCallFinder.php b/src/PluginValidate/Finder/FunctionCallFinder.php new file mode 100644 index 00000000..a5d68c67 --- /dev/null +++ b/src/PluginValidate/Finder/FunctionCallFinder.php @@ -0,0 +1,37 @@ +parser->parseFile($file); + + foreach ($this->filter->filterFunctionCalls($statements) as $funccall) { + if ($funccall->name instanceof Name) { + $fileTokens->compare((string) $funccall->name); + } + } + } +} diff --git a/src/PluginValidate/PluginValidate.php b/src/PluginValidate/PluginValidate.php index 93c03b82..2b0130ed 100644 --- a/src/PluginValidate/PluginValidate.php +++ b/src/PluginValidate/PluginValidate.php @@ -17,6 +17,7 @@ use MoodlePluginCI\PluginValidate\Finder\ClassFinder; use MoodlePluginCI\PluginValidate\Finder\FileTokens; use MoodlePluginCI\PluginValidate\Finder\FinderInterface; +use MoodlePluginCI\PluginValidate\Finder\FunctionCallFinder; use MoodlePluginCI\PluginValidate\Finder\FunctionFinder; use MoodlePluginCI\PluginValidate\Finder\LangFinder; use MoodlePluginCI\PluginValidate\Finder\TableFinder; @@ -115,6 +116,7 @@ public function verifyRequirements(): void $this->findRequiredTokens(new TableFinder(), [$this->requirements->getRequiredTables()]); $this->findRequiredTokens(new TablePrefixFinder(), [$this->requirements->getRequiredTablePrefix()]); $this->findRequiredTokens(new BehatTagFinder(), $this->requirements->getRequiredBehatTags()); + $this->findRequiredTokens(new FunctionCallFinder(), $this->requirements->getRequiredFunctionCalls()); } /** diff --git a/src/PluginValidate/Requirements/AbstractRequirements.php b/src/PluginValidate/Requirements/AbstractRequirements.php index 9978dd2f..1f5670b8 100644 --- a/src/PluginValidate/Requirements/AbstractRequirements.php +++ b/src/PluginValidate/Requirements/AbstractRequirements.php @@ -64,6 +64,13 @@ protected function behatTagsFactory(array $tags): array return $fileTokens; } + /** + * Required function calls. + * + * @return FileTokens[] + */ + abstract public function getRequiredFunctionCalls(): array; + /** * An array of required files, paths are relative to the plugin directory. * diff --git a/src/PluginValidate/Requirements/FilterRequirements.php b/src/PluginValidate/Requirements/FilterRequirements.php index cbed68db..86aea4a6 100644 --- a/src/PluginValidate/Requirements/FilterRequirements.php +++ b/src/PluginValidate/Requirements/FilterRequirements.php @@ -21,15 +21,24 @@ class FilterRequirements extends GenericRequirements { public function getRequiredFiles(): array { - return array_merge(parent::getRequiredFiles(), [ - 'filter.php', - ]); + $files = ['filter.php']; + if ($this->moodleVersion >= 405) { + $files[] = 'classes/text_filter.php'; + } + + return array_merge(parent::getRequiredFiles(), $files); } public function getRequiredClasses(): array { + if ($this->moodleVersion <= 404) { + return [ + FileTokens::create('filter.php')->mustHave('filter_' . $this->plugin->name), + ]; + } + return [ - FileTokens::create('filter.php')->mustHave('filter_' . $this->plugin->name), + FileTokens::create('classes/text_filter.php')->mustHave("filter_{$this->plugin->name}\\text_filter"), ]; } @@ -37,4 +46,15 @@ public function getRequiredStrings(): FileTokens { return FileTokens::create($this->getLangFile())->mustHave('filtername'); } + + public function getRequiredFunctionCalls(): array + { + if ($this->moodleVersion <= 404) { + return []; + } + + return [ + FileTokens::create('filter.php')->mustHave('class_alia'), + ]; + } } diff --git a/src/PluginValidate/Requirements/GenericRequirements.php b/src/PluginValidate/Requirements/GenericRequirements.php index d1dccf4f..d6cd412b 100644 --- a/src/PluginValidate/Requirements/GenericRequirements.php +++ b/src/PluginValidate/Requirements/GenericRequirements.php @@ -46,6 +46,11 @@ public function getRequiredClasses(): array return []; } + public function getRequiredFunctionCalls(): array + { + return []; + } + public function getRequiredStrings(): FileTokens { return FileTokens::create($this->getLangFile())->mustHave('pluginname'); diff --git a/tests/PluginValidate/Requirements/FilterRequirementsTest.php b/tests/PluginValidate/Requirements/FilterRequirementsTest.php index de2b2d4d..82ba1c2e 100644 --- a/tests/PluginValidate/Requirements/FilterRequirementsTest.php +++ b/tests/PluginValidate/Requirements/FilterRequirementsTest.php @@ -25,12 +25,14 @@ class FilterRequirementsTest extends \PHPUnit\Framework\TestCase protected function setUp(): void { - $this->requirements = new FilterRequirements(new Plugin('filter_activitynames', 'filter', 'activitynames', ''), 29); + $this->requirements404 = new FilterRequirements(new Plugin('filter_activitynames', 'filter', 'activitynames', ''), 404); + $this->requirements = new FilterRequirements(new Plugin('filter_activitynames', 'filter', 'activitynames', ''), 405); } protected function tearDown(): void { - $this->requirements = null; + $this->requirements404 = null; + $this->requirements = null; } public function testResolveRequirements() @@ -39,29 +41,50 @@ public function testResolveRequirements() $this->assertInstanceOf( 'MoodlePluginCI\PluginValidate\Requirements\FilterRequirements', - $resolver->resolveRequirements(new Plugin('', 'filter', '', ''), 29) + $resolver->resolveRequirements(new Plugin('', 'filter', '', ''), 404) ); } + public function testGetRequiredFiles404() + { + $files = $this->requirements404->getRequiredFiles(); + + $this->assertTrue(in_array('filter.php', $files, true)); + $this->assertFalse(in_array('classes/text_filter.php', $files, true)); + foreach ($files as $file) { + $this->assertIsString($file); + } + } + public function testGetRequiredFiles() { $files = $this->requirements->getRequiredFiles(); - $this->assertNotEmpty($files); $this->assertTrue(in_array('filter.php', $files, true)); + $this->assertTrue(in_array('classes/text_filter.php', $files, true)); foreach ($files as $file) { $this->assertIsString($file); } } + public function testGetRequiredClasses404() + { + $classes = $this->requirements404->getRequiredClasses(); + + $this->assertCount(1, $classes); + $class = reset($classes); + $this->assertInstanceOf('MoodlePluginCI\PluginValidate\Finder\FileTokens', $class); + $this->assertSame('filter.php', $class->file); + } + public function testGetRequiredClasses() { $classes = $this->requirements->getRequiredClasses(); - $this->assertNotEmpty($classes); - foreach ($classes as $class) { - $this->assertInstanceOf('MoodlePluginCI\PluginValidate\Finder\FileTokens', $class); - } + $this->assertCount(1, $classes); + $class = reset($classes); + $this->assertInstanceOf('MoodlePluginCI\PluginValidate\Finder\FileTokens', $class); + $this->assertSame('classes/text_filter.php', $class->file); } public function testGetRequiredStrings()