diff options
author | Arthur Schiwon <blizzz@arthur-schiwon.de> | 2023-11-17 14:04:09 +0100 |
---|---|---|
committer | Arthur Schiwon <blizzz@arthur-schiwon.de> | 2023-11-24 12:46:38 +0100 |
commit | 3fa43a529bbef075364666c5122e7ad18d34de62 (patch) | |
tree | a74e60d3da87fb32222dcb1176747a35eff9f368 /lib/private/AppFramework/Utility | |
parent | 7646f68cd7e4dcba44a1c54258a3fe2a0cf18a36 (diff) | |
download | nextcloud-server-3fa43a529bbef075364666c5122e7ad18d34de62.tar.gz nextcloud-server-3fa43a529bbef075364666c5122e7ad18d34de62.zip |
enh(dispatcher): enforce psalm ranges in the http dispatcher
- allows devs to provide int ranges for API arguments
Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>
Diffstat (limited to 'lib/private/AppFramework/Utility')
-rw-r--r-- | lib/private/AppFramework/Utility/ControllerMethodReflector.php | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/lib/private/AppFramework/Utility/ControllerMethodReflector.php b/lib/private/AppFramework/Utility/ControllerMethodReflector.php index b76b3c33c42..5a1ed0fd6ee 100644 --- a/lib/private/AppFramework/Utility/ControllerMethodReflector.php +++ b/lib/private/AppFramework/Utility/ControllerMethodReflector.php @@ -42,6 +42,7 @@ class ControllerMethodReflector implements IControllerMethodReflector { public $annotations = []; private $types = []; private $parameters = []; + private array $ranges = []; /** * @param object $object an object or classname @@ -54,26 +55,38 @@ class ControllerMethodReflector implements IControllerMethodReflector { if ($docs !== false) { // extract everything prefixed by @ and first letter uppercase preg_match_all('/^\h+\*\h+@(?P<annotation>[A-Z]\w+)((?P<parameter>.*))?$/m', $docs, $matches); - foreach ($matches['annotation'] as $key => $annontation) { - $annontation = strtolower($annontation); + foreach ($matches['annotation'] as $key => $annotation) { + $annotation = strtolower($annotation); $annotationValue = $matches['parameter'][$key]; if (isset($annotationValue[0]) && $annotationValue[0] === '(' && $annotationValue[\strlen($annotationValue) - 1] === ')') { $cutString = substr($annotationValue, 1, -1); $cutString = str_replace(' ', '', $cutString); - $splittedArray = explode(',', $cutString); - foreach ($splittedArray as $annotationValues) { + $splitArray = explode(',', $cutString); + foreach ($splitArray as $annotationValues) { [$key, $value] = explode('=', $annotationValues); - $this->annotations[$annontation][$key] = $value; + $this->annotations[$annotation][$key] = $value; } continue; } - $this->annotations[$annontation] = [$annotationValue]; + $this->annotations[$annotation] = [$annotationValue]; } // extract type parameter information preg_match_all('/@param\h+(?P<type>\w+)\h+\$(?P<var>\w+)/', $docs, $matches); $this->types = array_combine($matches['var'], $matches['type']); + preg_match_all('/@psalm-param\h+(?P<type>\w+)<(?P<rangeMin>(-?\d+|min)),\h*(?P<rangeMax>(-?\d+|max))>\h+\$(?P<var>\w+)/', $docs, $matches); + foreach ($matches['var'] as $index => $varName) { + if ($matches['type'][$index] !== 'int') { + // only int ranges are possible at the moment + // @see https://psalm.dev/docs/annotating_code/type_syntax/scalar_types + continue; + } + $this->ranges[$varName] = [ + 'min' => $matches['rangeMin'][$index] === 'min' ? PHP_INT_MIN : (int)$matches['rangeMin'][$index], + 'max' => $matches['rangeMax'][$index] === 'max' ? PHP_INT_MAX : (int)$matches['rangeMax'][$index], + ]; + } } foreach ($reflection->getParameters() as $param) { @@ -106,6 +119,14 @@ class ControllerMethodReflector implements IControllerMethodReflector { return null; } + public function getRange(string $parameter): ?array { + if (array_key_exists($parameter, $this->ranges)) { + return $this->ranges[$parameter]; + } + + return null; + } + /** * @return array the arguments of the method with key => default value */ |