Skip to content

Commit 2284369

Browse files
authored
Merge pull request #326 from kabalin/filter-req
Adjust filter plugin validation requirements to comply with Moodle 4.5
2 parents cd11318 + 1326d19 commit 2284369

File tree

13 files changed

+290
-13
lines changed

13 files changed

+290
-13
lines changed

.php-cs-fixer.cache

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

.phpunit.result.cache

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

docs/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@ This project adheres to [Semantic Versioning](https://semver.org/).
99
The format of this change log follows the advice given at [Keep a CHANGELOG](https://keepachangelog.com).
1010

1111
## [Unreleased]
12+
### Added
13+
- Improvements to plugin validation implementation:
14+
`getRequiredFunctionCalls` in plugin type specific `Requirements` class can be used to validate that file contains function call.
15+
`FileTokens::notFoundHint` can be used to give some context for validation error to improve developer experience.
16+
1217
### Fixed
1318
- Fixed stylelinting error in non-theme plugins containing scss.
19+
- Updated filter plugin validation requirements to comply with Moodle 4.5
1420

1521
### Removed
1622
- Stylelint less component task (`grunt stylelint:less`) has been deprecated in

src/Parser/StatementFilter.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414

1515
use PhpParser\Node\Expr\Array_;
1616
use PhpParser\Node\Expr\Assign;
17+
use PhpParser\Node\Expr\FuncCall;
1718
use PhpParser\Node\Expr\PropertyFetch;
1819
use PhpParser\Node\Expr\Variable;
1920
use PhpParser\Node\Identifier;
21+
use PhpParser\Node\Name;
2022
use PhpParser\Node\Scalar\String_;
2123
use PhpParser\Node\Stmt;
2224
use PhpParser\Node\Stmt\Class_;
@@ -116,6 +118,26 @@ public function filterAssignments(array $statements): array
116118
return $assigns;
117119
}
118120

121+
/**
122+
* Extract all the function call expressions from the statements.
123+
*
124+
* @param Stmt[] $statements
125+
*
126+
* @return FuncCall[]
127+
*/
128+
public function filterFunctionCalls(array $statements): array
129+
{
130+
$calls = [];
131+
foreach ($statements as $statement) {
132+
// Only expressions that are function calls.
133+
if ($statement instanceof Expression && $statement->expr instanceof FuncCall) {
134+
$calls[] = $statement->expr;
135+
}
136+
}
137+
138+
return $calls;
139+
}
140+
119141
/**
120142
* Find first variable assignment with a given name.
121143
*

src/PluginValidate/Finder/FileTokens.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@ class FileTokens
2929
*/
3030
public string $file;
3131

32+
/**
33+
* Not found error hint.
34+
*
35+
* @var string
36+
*/
37+
public string $hint = '';
38+
3239
/**
3340
* @param string $file
3441
*/
@@ -59,6 +66,16 @@ public function hasTokens(): bool
5966
return !empty($this->tokens);
6067
}
6168

69+
/**
70+
* Do we have any hint?
71+
*
72+
* @return bool
73+
*/
74+
public function hasHint(): bool
75+
{
76+
return !empty($this->hint);
77+
}
78+
6279
/**
6380
* @param Token $token
6481
*
@@ -166,4 +183,18 @@ public function resetTokens(): void
166183
$token->reset();
167184
}
168185
}
186+
187+
/**
188+
* Not found error additional information guiding user how to fix it (optional).
189+
*
190+
* @param string $hint
191+
*
192+
* @return self
193+
*/
194+
public function notFoundHint(string $hint): self
195+
{
196+
$this->hint = $hint;
197+
198+
return $this;
199+
}
169200
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Moodle Plugin CI package.
5+
*
6+
* For the full copyright and license information, please view the LICENSE
7+
* file that was distributed with this source code.
8+
*
9+
* Copyright (c) 2024 Moodle Pty Ltd <[email protected]>
10+
* License http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
11+
*/
12+
13+
namespace MoodlePluginCI\PluginValidate\Finder;
14+
15+
use PhpParser\Node\Name;
16+
17+
/**
18+
* Finds function call.
19+
*/
20+
class FunctionCallFinder extends AbstractParserFinder
21+
{
22+
public function getType(): string
23+
{
24+
return 'function call';
25+
}
26+
27+
public function findTokens($file, FileTokens $fileTokens): void
28+
{
29+
$statements = $this->parser->parseFile($file);
30+
31+
foreach ($this->filter->filterFunctionCalls($statements) as $funccall) {
32+
if ($funccall->name instanceof Name) {
33+
$fileTokens->compare((string) $funccall->name);
34+
}
35+
}
36+
}
37+
}

src/PluginValidate/PluginValidate.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use MoodlePluginCI\PluginValidate\Finder\ClassFinder;
1818
use MoodlePluginCI\PluginValidate\Finder\FileTokens;
1919
use MoodlePluginCI\PluginValidate\Finder\FinderInterface;
20+
use MoodlePluginCI\PluginValidate\Finder\FunctionCallFinder;
2021
use MoodlePluginCI\PluginValidate\Finder\FunctionFinder;
2122
use MoodlePluginCI\PluginValidate\Finder\LangFinder;
2223
use MoodlePluginCI\PluginValidate\Finder\TableFinder;
@@ -98,6 +99,9 @@ public function addMessagesFromTokens(string $type, FileTokens $fileTokens): voi
9899
$this->addSuccess(sprintf('In %s, found %s %s', $fileTokens->file, $type, implode(' OR ', $token->tokens)));
99100
} else {
100101
$this->addError(sprintf('In %s, failed to find %s %s', $fileTokens->file, $type, implode(' OR ', $token->tokens)));
102+
if ($fileTokens->hasHint()) {
103+
$this->addError(sprintf('Hint: %s', $fileTokens->hint));
104+
}
101105
}
102106
}
103107
}
@@ -115,6 +119,7 @@ public function verifyRequirements(): void
115119
$this->findRequiredTokens(new TableFinder(), [$this->requirements->getRequiredTables()]);
116120
$this->findRequiredTokens(new TablePrefixFinder(), [$this->requirements->getRequiredTablePrefix()]);
117121
$this->findRequiredTokens(new BehatTagFinder(), $this->requirements->getRequiredBehatTags());
122+
$this->findRequiredTokens(new FunctionCallFinder(), $this->requirements->getRequiredFunctionCalls());
118123
}
119124

120125
/**

src/PluginValidate/Requirements/AbstractRequirements.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,25 @@ protected function behatTagsFactory(array $tags): array
6464
return $fileTokens;
6565
}
6666

67+
/**
68+
* Helper method to check file existence.
69+
*
70+
* @param string $file
71+
*
72+
* @return bool
73+
*/
74+
protected function fileExists(string $file): bool
75+
{
76+
return file_exists($this->plugin->directory . '/' . $file);
77+
}
78+
79+
/**
80+
* Required function calls.
81+
*
82+
* @return FileTokens[]
83+
*/
84+
abstract public function getRequiredFunctionCalls(): array;
85+
6786
/**
6887
* An array of required files, paths are relative to the plugin directory.
6988
*

src/PluginValidate/Requirements/FilterRequirements.php

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,44 @@ class FilterRequirements extends GenericRequirements
2121
{
2222
public function getRequiredFiles(): array
2323
{
24-
return array_merge(parent::getRequiredFiles(), [
25-
'filter.php',
26-
]);
24+
$files = [];
25+
if ($this->moodleVersion >= 405) {
26+
$files[] = 'classes/text_filter.php';
27+
} else {
28+
// This must exist in 4.5 if plugin supports older version, but we don't identify support range to validate it.
29+
$files[] = 'filter.php';
30+
}
31+
32+
return array_merge(parent::getRequiredFiles(), $files);
2733
}
2834

2935
public function getRequiredClasses(): array
3036
{
37+
if ($this->moodleVersion <= 404 && !$this->fileExists('classes/text_filter.php')) {
38+
// Plugin does not support 4.5, check class presence in filter.php
39+
return [
40+
FileTokens::create('filter.php')->mustHave('filter_' . $this->plugin->name),
41+
];
42+
}
43+
3144
return [
32-
FileTokens::create('filter.php')->mustHave('filter_' . $this->plugin->name),
45+
FileTokens::create('classes/text_filter.php')->mustHave("filter_{$this->plugin->name}\\text_filter"),
3346
];
3447
}
3548

3649
public function getRequiredStrings(): FileTokens
3750
{
3851
return FileTokens::create($this->getLangFile())->mustHave('filtername');
3952
}
53+
54+
public function getRequiredFunctionCalls(): array
55+
{
56+
if ($this->moodleVersion <= 404 && !$this->fileExists('classes/text_filter.php')) {
57+
return [];
58+
}
59+
60+
return [
61+
FileTokens::create('filter.php')->mustHave('class_alias')->notFoundHint('https://moodledev.io/docs/4.5/devupdate#filter-plugins'),
62+
];
63+
}
4064
}

src/PluginValidate/Requirements/GenericRequirements.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ public function getRequiredClasses(): array
4646
return [];
4747
}
4848

49+
public function getRequiredFunctionCalls(): array
50+
{
51+
return [];
52+
}
53+
4954
public function getRequiredStrings(): FileTokens
5055
{
5156
return FileTokens::create($this->getLangFile())->mustHave('pluginname');

0 commit comments

Comments
 (0)