Skip to content

Commit

Permalink
Added basic metadata validation.
Browse files Browse the repository at this point in the history
  • Loading branch information
zerai committed Sep 20, 2024
1 parent f498fc6 commit 563cf68
Show file tree
Hide file tree
Showing 5 changed files with 287 additions and 26 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@

namespace Metadata\Core\MetadataValidationEngine;

/**
* @throws MetadataValidationException
*/
interface ForMetadataSchemaValidation
{
public function validate(array $metadata): bool;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
class MetadataValidationException extends \Exception
{
public function __construct(
string $message = '',
int $code = 0,
?\Throwable $previous = null
) {
$message = 'Metadata validation error';
parent::__construct($message, $code, $previous);
$errorMessage = ($message === '') ? 'Metadata validation error' : $message;
parent::__construct($errorMessage, $code, $previous);
}
}
76 changes: 76 additions & 0 deletions _metadata/src/Core/MetadataValidationEngine/MetadataValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php declare(strict_types=1);

/**
* This file is part of the medicalmundi/marketplace-engine
*
* @copyright (c) 2024 MedicalMundi
*
* This software consists of voluntary contributions made by many individuals
* {@link https://github.com/medicalmundi/marketplace-engine/graphs/contributors developer} and is licensed under the MIT license.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
* @license https://github.com/MedicalMundi/marketplace-engine/blob/main/LICENSE MIT
*/

namespace Metadata\Core\MetadataValidationEngine;

class MetadataValidator implements ForMetadataSchemaValidation
{
private const ALLOWED_CATEGORY = [
'administration',
'billing',
'ePrescribing',
'miscellaneous',
'telecom',
'telehealth',
'payment',
];

private const ALLOWED_TAG = [
'fax',
'organizer',
'reminder',
'scheduler',
'sms',
'todo',
];

/**
* @throws MetadataValidationException
*/
public function validate(array $metadata): bool
{
if (! \array_key_exists('category', $metadata)) {
throw new MetadataValidationException('Metadata key \'category\' not found');
} else {
$category = $metadata['category'];

if (! \is_string($category)) {
throw new MetadataValidationException('Metadata \'Category\' should be string type');
}

if (! \in_array($category, self::ALLOWED_CATEGORY)) {
throw new MetadataValidationException('Category not allowed: ' . $category);
}
}

if (! \array_key_exists('tags', $metadata)) {
throw new MetadataValidationException('Metadata key \'tags\' not found');
} else {
$tags = $metadata['tags'];

if (! \is_array($tags)) {
throw new MetadataValidationException('Metadata \'tags\' should be array type');
}
/** @var string $tag */
foreach ($tags as $tag) {
if (! \in_array($tag, self::ALLOWED_TAG)) {
throw new MetadataValidationException('Tag not allowed: ' . $tag);
}
}
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
<?php declare(strict_types=1);

/**
* This file is part of the medicalmundi/marketplace-engine
*
* @copyright (c) 2024 MedicalMundi
*
* This software consists of voluntary contributions made by many individuals
* {@link https://github.com/medicalmundi/marketplace-engine/graphs/contributors developer} and is licensed under the MIT license.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
* @license https://github.com/MedicalMundi/marketplace-engine/blob/main/LICENSE MIT
*/

namespace MetadataTests\Unit\Core\MetadataValidationEngine;

use Metadata\Core\MetadataValidationEngine\MetadataValidationException;
use Metadata\Core\MetadataValidationEngine\MetadataValidator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

#[CoversClass(MetadataValidator::class)]
class MetadataValidatorTest extends TestCase
{
#[Test]
public function shouldFailWhenThereIsNoCategoryKey(): void
{
self::expectException(MetadataValidationException::class);
self::expectExceptionMessage('Metadata key \'category\' not found');
$validator = new MetadataValidator();

$validator->validate([
'tags' => 'irrelevant',
]);
}

#[Test]
#[DataProvider('invalidCategoryDataprovider')]
public function shouldFailWhenCategoryIsNotValid(array $metadata): void
{
self::expectException(MetadataValidationException::class);
self::expectExceptionMessage('Metadata \'Category\' should be string type');

$validator = new MetadataValidator();
$validator->validate($metadata);
}

#[Test]
public function shouldFailWhenThereIsNoTagsKey(): void
{
self::expectException(MetadataValidationException::class);
self::expectExceptionMessage('Metadata key \'tags\' not found');
$validator = new MetadataValidator();

$validator->validate([
'category' => 'billing',
]);
}

#[Test]
#[DataProvider('invalidTagsDataprovider')]
public function shouldFailWhenTagsIsNotValid(array $metadata): void
{
self::expectException(MetadataValidationException::class);
self::expectExceptionMessage('Metadata \'tags\' should be array type');

$validator = new MetadataValidator();
$validator->validate($metadata);
}

#[Test]
public function shouldPassTheValidation(): void
{
$validator = new MetadataValidator();

$result = $validator->validate([
'category' => 'billing',
'tags' => ['fax', 'sms'],
]);

self::assertTrue($result);
}

#[Test]
#[DataProvider('approvedCategoryDataprovider')]
#[DataProvider('approvedTagsDataprovider')]
public function shouldPassTheValidationOnlyWithApprovedCategoryAndTags(array $metadata): void
{
$validator = new MetadataValidator();

$result = $validator->validate($metadata);

self::assertTrue($result);
}

public static function invalidCategoryDataprovider(): array
{
return [
[[
'category' => null,
'tags' => 'irrelevant',
]],
[[
'category' => 0,
'tags' => 'irrelevant',
]],
[[
'category' => [],
'tags' => 'irrelevant',
]],
[[
'category' => new \stdClass(),
'tags' => 'irrelevant',
]],
];
}

public static function invalidTagsDataprovider(): array
{
return [
[[
'category' => 'billing',
'tags' => null,
]],
[[
'category' => 'billing',
'tags' => 0,
]],
[[
'category' => 'billing',
'tags' => 'string',
]],
[[
'category' => 'billing',
'tags' => new \stdClass(),
]],
[[
'category' => 'billing',
'tags' => 'not allowed',
]],
];
}

public static function approvedCategoryDataprovider(): array
{
return [
[[
'category' => 'administration',
'tags' => ['fax'],
]],
[[
'category' => 'billing',
'tags' => ['fax'],
]],
[[
'category' => 'ePrescribing',
'tags' => ['fax'],
]],
[[
'category' => 'miscellaneous',
'tags' => ['fax'],
]],
[[
'category' => 'telecom',
'tags' => ['fax'],
]],
[[
'category' => 'telehealth',
'tags' => ['fax'],
]],
[[
'category' => 'payment',
'tags' => ['fax'],
]],
];
}

public static function approvedTagsDataprovider(): array
{
return [
[[
'category' => 'miscellaneous',
'tags' => ['fax'],
]],
[[
'category' => 'miscellaneous',
'tags' => ['organizer'],
]],
[[
'category' => 'miscellaneous',
'tags' => ['scheduler'],
]],
[[
'category' => 'miscellaneous',
'tags' => ['todo'],
]],



];
}
}

0 comments on commit 563cf68

Please sign in to comment.