Skip to content

Commit

Permalink
Add validator v2
Browse files Browse the repository at this point in the history
  • Loading branch information
Sandy Tseng committed Oct 23, 2024
1 parent 93b63f2 commit f7ccea6
Showing 1 changed file with 171 additions and 0 deletions.
171 changes: 171 additions & 0 deletions src/Validator/SchemaValidatorV2.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
<?php

namespace Tmilos\ScimSchema\Validator;

use Tmilos\ScimSchema\Helper;
use Tmilos\ScimSchema\Model\Schema\Attribute;
use Tmilos\ScimSchema\Model\Schema;
use Tmilos\ScimSchema\ScimConstants;

class SchemaValidatorV2
{
private static array $commonAttributes = [
'id' => 1,
'schemas' => 1,
'externalId' => 1,
'meta' => 1,
];

/**
* @param Schema[] $schemaExtensions
*/
public function validate(array $object, Schema $schema, array $schemaExtensions = []): ValidationResult
{
$validationResult = new ValidationResult();
/** @var Schema[] $otherSchemas */
$otherSchemas = [];
foreach ($schemaExtensions as $schemaExtension) {
$otherSchemas[$schemaExtension->getId()] = $schemaExtension;
}

$this->validateByAttributes(
$object,
$schema->getId(),
$schema->getAttributes(),
$otherSchemas,
$validationResult,
null,
);

foreach ($otherSchemas as $schemaId => $otherSchema) {
if (isset($object[$schemaId])) {
$this->validateByAttributes(
$object[$schemaId],
$otherSchema->getId(),
$otherSchema->getAttributes(),
[],
$validationResult,
null,
);
}
}

return $validationResult;
}

/**
* @param Attribute[] $attributes
*/
private function validateByAttributes(
array $object,
string $schemaId,
array $attributes,
array $ignoreAttributes,
ValidationResult $validationResult,
?string $parentPath,
): void {
foreach ($object as $propertyName => $value) {
if ($parentPath === null && isset(self::$commonAttributes[$propertyName])) {
// skip common resource attributes
continue;
}
if ($parentPath === null && isset($ignoreAttributes[$propertyName])) {
continue;
}

$attribute = Helper::findAttribute($propertyName, $attributes);
if (!$attribute) {
continue;
}

if ($attribute->isRequired() === false && $value === null) {
continue;
}

if ($this->isArray($value)) {
if (!$attribute->isMultiValued()) {
$validationResult->add(
$propertyName,
$parentPath,
$schemaId,
'Attribute is not defined in schema as multi-valued, but got array',
);
continue;
} else {
foreach ($value as $item) {
$this->validateByAttributes(
$item,
$schemaId,
$attribute->getSubAttributes(),
[],
$validationResult,
$propertyName,
);
}
}
} elseif ($this->isObject($value)) {
if ($attribute->isMultiValued()) {
$validationResult->add(
$propertyName,
$parentPath,
$schemaId,
'Attribute is defined in schema as multi-valued, but got object',
);
continue;
} elseif ($attribute->getType() !== ScimConstants::ATTRIBUTE_TYPE_COMPLEX) {
$validationResult->add(
$propertyName,
$parentPath,
$schemaId,
'Attribute is not defined in schema as complex, but got object',
);
continue;
}
$this->validateByAttributes(
$value,
$schemaId,
$attribute->getSubAttributes(),
[],
$validationResult,
$propertyName,
);
} else {
if ($attribute->isMultiValued()) {
$validationResult->add(
$propertyName,
$parentPath,
$schemaId,
'Attribute is defined in schema as multi-valued, but got scalar',
);
continue;
} elseif ($attribute->getType() === ScimConstants::ATTRIBUTE_TYPE_COMPLEX) {
$validationResult->add(
$propertyName,
$parentPath,
$schemaId,
'Attribute is defined in schema as complex, but got scalar',
);
continue;
} elseif (!$attribute->isValueValid($value)) {
$validationResult->add(
$propertyName,
$parentPath,
$schemaId,
sprintf('Attribute has invalid value for type "%s"', $attribute->getType()),
);
continue;
}
}
}
}

private function isArray(mixed $value): bool
{
return is_array($value) && Helper::hasAllIntKeys($value);
}

private function isObject(mixed $value): bool
{
return is_array($value) && Helper::hasAllStringKeys($value);
}
}

0 comments on commit f7ccea6

Please sign in to comment.