Skip to content

Commit

Permalink
added fields to attributes for extraction, formats are now referenced…
Browse files Browse the repository at this point in the history
… with classnames, not hardcoded strings
  • Loading branch information
eceltov committed Jan 23, 2025
1 parent 19be393 commit e497148
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 116 deletions.
5 changes: 4 additions & 1 deletion app/helpers/MetaFormats/Attributes/FormatAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@
#[Attribute]
class FormatAttribute
{
public function __construct(string $format)
public string $class;

public function __construct(string $class)
{
$this->class = $class;
}
}
23 changes: 21 additions & 2 deletions app/helpers/MetaFormats/Attributes/FormatParameterAttribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,26 @@
#[Attribute]
class FormatParameterAttribute
{
public function __construct(RequestParamType $type, string $description = "", bool $required = true)
{
public RequestParamType $type;
public string $description;
public bool $required;
public array $validators;

/**
* @param \App\Helpers\MetaFormats\RequestParamType $type The request parameter type (Post or Query).
* @param string $description The description of the request parameter.
* @param bool $required Whether the request parameter is required.
* @param array $validators An array of validators applied to the request parameter.
*/
public function __construct(
RequestParamType $type,
string $description = "",
bool $required = true,
array $validators = [],
) {
$this->type = $type;
$this->description = $description;
$this->required = $required;
$this->validators = $validators;
}
}
8 changes: 0 additions & 8 deletions app/helpers/MetaFormats/FormatCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,6 @@ public static function getFormatFieldNames(string $format): array
return array_keys($formatToFieldDefinitionsMap[$format]);
}

public static function getValidators(): array
{
if (self::$validators == null) {
self::$validators = MetaFormatHelper::getValidators();
}
return self::$validators;
}

public static function getFieldDefinitions(string $className)
{
$classToFormatMap = self::getClassToFormatMap();
Expand Down
2 changes: 1 addition & 1 deletion app/helpers/MetaFormats/FormatDefinitions/GroupFormat.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use App\Helpers\MetaFormats\Attributes\FormatAttribute;
use App\Helpers\MetaFormats\MetaFormat;

#[FormatAttribute("group")]
#[FormatAttribute(GroupFormat::class)]
class GroupFormat extends MetaFormat
{
// #[FormatAttribute("uuid")]
Expand Down
2 changes: 1 addition & 1 deletion app/helpers/MetaFormats/FormatDefinitions/UserFormat.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use App\Helpers\MetaFormats\Attributes\FormatParameterAttribute;
use App\Helpers\MetaFormats\RequestParamType;

#[FormatAttribute("userRegistration")]
#[FormatAttribute(UserFormat::class)]
class UserFormat extends MetaFormat
{
#[FormatAttribute("email")]
Expand Down
90 changes: 28 additions & 62 deletions app/helpers/MetaFormats/MetaFormatHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ public static function extractMethodCheckedParams(string $className, string $met
* Checks whether an entity contains a FormatAttribute and extracts the format if so.
* @param \ReflectionClass|\ReflectionProperty|\ReflectionMethod $reflectionObject A reflection
* object of the entity.
* @throws \App\Exceptions\InternalServerException Thrown when the FormatAttribute was used incorrectly.
* @return ?string Returns the format or null if no FormatAttribute was present.
*/
public static function extractFormatFromAttribute(
Expand All @@ -78,14 +77,8 @@ public static function extractFormatFromAttribute(
return null;
}

// check attribute correctness
$formatArguments = $formatAttributes[0]->getArguments();
if (count($formatArguments) !== 1) {
$name = $reflectionObject->getName();
throw new InternalServerException("The entity $name does not have a single attribute argument.");
}

return $formatArguments[0];
$formatAttribute = $formatAttributes[0]->newInstance();
return $formatAttribute->class;
}

/**
Expand All @@ -111,36 +104,36 @@ public static function extractRequestParamData(ReflectionMethod $reflectionMetho
return $data;
}

public static function extractRequestAttributeData(
ReflectionClass|ReflectionProperty|ReflectionMethod $reflectionObject
): ?RequestParamData {
$requestAttribute = $reflectionObject->getAttributes(FormatParameterAttribute::class);
if (count($requestAttribute) === 0) {
public static function extractFormatParameterData(ReflectionProperty $reflectionObject): ?RequestParamData
{
$requestAttributes = $reflectionObject->getAttributes(FormatParameterAttribute::class);
if (count($requestAttributes) === 0) {
return null;
}

$requestArguments = $requestAttribute[0]->getArguments();
$name = $reflectionObject->name;
$type = $requestArguments["type"];
$description = array_key_exists("description", $requestArguments) ? $requestArguments["description"] : "";
$required = array_key_exists("required", $requestArguments) ? $requestArguments["required"] : true;

return new RequestParamData($type, $name, $description, $required);
$requestAttribute = $requestAttributes[0]->newInstance();
return new RequestParamData(
$requestAttribute->type,
$reflectionObject->name,
$requestAttribute->description,
$requestAttribute->required,
$requestAttribute->validators
);
}

/**
* Debug method used to extract all attribute data of a reflection object.
* @param \ReflectionClass|\ReflectionProperty|\ReflectionMethod $reflectionObject The reflection object.
* @return array Returns an array, where each element represents an attribute in top-down order of definition
* in the code. Each element is an array of constructor arguments of the attribute.
* in the code. Each element is an instance of the specific attribute.
*/
public static function debugGetAttributes(
ReflectionClass|ReflectionProperty|ReflectionMethod $reflectionObject
): array {
$requestAttributes = $reflectionObject->getAttributes();
$data = [];
foreach ($requestAttributes as $attr) {
$data[] = $attr->getArguments();
$data[] = $attr->newInstance();
}
return $data;
}
Expand All @@ -164,7 +157,7 @@ public static function createNameToFieldDefinitionsMap(string $className)
$fieldType = $reflectionType?->getName();

Check failure on line 157 in app/helpers/MetaFormats/MetaFormatHelper.php

View workflow job for this annotation

GitHub Actions / phpstan (8.2)

Call to an undefined method ReflectionType::getName().

Check failure on line 157 in app/helpers/MetaFormats/MetaFormatHelper.php

View workflow job for this annotation

GitHub Actions / phpstan (8.3)

Call to an undefined method ReflectionType::getName().
$nullable = $reflectionType?->allowsNull() ?? false;

$requestParamData = self::extractRequestAttributeData($field);
$requestParamData = self::extractFormatParameterData($field);
if ($requestParamData === null) {
throw new InternalServerException(
"The field $fieldName of class $className does not have a RequestAttribute."
Expand Down Expand Up @@ -210,44 +203,6 @@ public static function createFormatToClassMap()
return $formatClassMap;
}

/**
* Extracts all primitive validator methods (starting with "validate") and returns a map from format to a callback.
* The callbacks have one parameter that is passed to the validator.
*/
private static function getPrimitiveValidators(): array
{
$instance = new PrimitiveFormatValidators();
$className = get_class($instance);
$methodNames = get_class_methods($className);

$validators = [];
foreach ($methodNames as $methodName) {
// all validation methods start with validate
if (!str_starts_with($methodName, "validate")) {
continue;
}

$annotations = AnnotationHelper::getMethodAnnotations($className, $methodName);
$format = self::extractFormatData($annotations);
$callback = function ($param) use ($instance, $methodName) {
return $instance->$methodName($param);
};
$validators[$format] = $callback;
}

return $validators;
}

private static function getMetaValidators(): array
{
return [];
}

public static function getValidators(): array
{
return array_merge(self::getPrimitiveValidators(), self::getMetaValidators());
}

/**
* Creates a MetaFormat instance of the given format.
* @param string $format The name of the format.
Expand All @@ -265,4 +220,15 @@ public static function createFormatInstance(string $format): MetaFormat
$instance = new $className();
return $instance;
}

/**
* Checks whether a value is of a given type.
* @param mixed $value The value to be tested.
* @param \App\Helpers\MetaFormats\PhpTypes $type The desired type of the value.
* @return bool Returns whether the value is of the given type.
*/
public static function checkType($value, PhpTypes $type): bool
{
return gettype($value) === $type->value;
}
}
39 changes: 0 additions & 39 deletions app/helpers/MetaFormats/PrimitiveFormatValidators.php

This file was deleted.

4 changes: 2 additions & 2 deletions app/helpers/MetaFormats/Validators/StringValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

namespace App\Helpers\MetaFormats\Validators;

use App\Helpers\MetaFormats\MetaFormatHelper;
use App\Helpers\MetaFormats\PhpTypes;
use App\Helpers\MetaFormats\PrimitiveFormatValidators;

class StringValidator
{
Expand All @@ -21,7 +21,7 @@ public function __construct(int $minLength = 0, int $maxLength = -1, ?string $re

public function validate(string $value)
{
if (!PrimitiveFormatValidators::checkType($value, PhpTypes::String)) {
if (!MetaFormatHelper::checkType($value, PhpTypes::String)) {
return false;
}

Expand Down

0 comments on commit e497148

Please sign in to comment.