Skip to content

Commit

Permalink
Merge pull request #88 from eliashaeussler/fix/change-frequency
Browse files Browse the repository at this point in the history
[BUGFIX] Loosen strict enumerations for change frequency
  • Loading branch information
eliashaeussler authored Sep 20, 2022
2 parents e54c6b0 + c24fd29 commit 475dce7
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 1 deletion.
61 changes: 61 additions & 0 deletions src/Normalizer/ChangeFrequencyNormalizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Composer package "eliashaeussler/cache-warmup".
*
* Copyright (C) 2022 Elias Häußler <elias@haeussler.dev>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

namespace EliasHaeussler\CacheWarmup\Normalizer;

use EliasHaeussler\CacheWarmup\Sitemap;
use Symfony\Component\PropertyInfo;
use Symfony\Component\Serializer;
use ValueError;

use function is_string;

/**
* ChangeFrequencyNormalizer.
*
* @author Elias Häußler <elias@haeussler.dev>
* @license GPL-3.0-or-later
*/
final class ChangeFrequencyNormalizer implements Serializer\Normalizer\DenormalizerInterface
{
/**
* @param array{deserialization_path?: string} $context
*/
public function denormalize(mixed $data, string $type, string $format = null, array $context = [])
{
if (!is_string($data)) {
throw Serializer\Exception\NotNormalizableValueException::createForUnexpectedDataType('Change frequency data must be a string.', $data, [PropertyInfo\Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, true);
}

try {
return Sitemap\ChangeFrequency::fromCaseInsensitive($data);
} catch (ValueError $error) {
throw Serializer\Exception\NotNormalizableValueException::createForUnexpectedDataType($error->getMessage(), $data, [PropertyInfo\Type::BUILTIN_TYPE_STRING], $context['deserialization_path'] ?? null, true, $error->getCode(), $error);
}
}

public function supportsDenormalization(mixed $data, string $type, string $format = null): bool
{
return Sitemap\ChangeFrequency::class === $type;
}
}
7 changes: 7 additions & 0 deletions src/Sitemap/ChangeFrequency.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@

namespace EliasHaeussler\CacheWarmup\Sitemap;

use function strtolower;

/**
* ChangeFrequency.
*
Expand All @@ -38,4 +40,9 @@ enum ChangeFrequency: string
case Monthly = 'monthly';
case Yearly = 'yearly';
case Never = 'never';

public static function fromCaseInsensitive(string $changeFrequency): self
{
return self::from(strtolower($changeFrequency));
}
}
2 changes: 1 addition & 1 deletion src/Xml/XmlParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public function parse(Sitemap\Sitemap $sitemap): Result\ParserResult
new Serializer\Normalizer\DateTimeNormalizer([
Serializer\Normalizer\DateTimeNormalizer::FORMAT_KEY => DateTimeInterface::W3C,
]),
new Serializer\Normalizer\BackedEnumNormalizer(),
new Normalizer\ChangeFrequencyNormalizer(),
new Serializer\Normalizer\ObjectNormalizer(
$classMetadataFactory = new Serializer\Mapping\Factory\ClassMetadataFactory(
new Serializer\Mapping\Loader\AnnotationLoader(new Annotations\AnnotationReader())
Expand Down
94 changes: 94 additions & 0 deletions tests/Unit/Normalizer/ChangeFrequencyNormalizerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Composer package "eliashaeussler/cache-warmup".
*
* Copyright (C) 2022 Elias Häußler <elias@haeussler.dev>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

namespace EliasHaeussler\CacheWarmup\Tests\Unit\Normalizer;

use EliasHaeussler\CacheWarmup\Normalizer;
use EliasHaeussler\CacheWarmup\Sitemap;
use Generator;
use PHPUnit\Framework;
use Symfony\Component\Serializer;

/**
* ChangeFrequencyNormalizerTest.
*
* @author Elias Häußler <elias@haeussler.dev>
* @license GPL-3.0-or-later
*/
final class ChangeFrequencyNormalizerTest extends Framework\TestCase
{
private Normalizer\ChangeFrequencyNormalizer $subject;

protected function setUp(): void
{
$this->subject = new Normalizer\ChangeFrequencyNormalizer();
}

/**
* @test
*/
public function denormalizeThrowsExceptionIfGivenDataIsNotAString(): void
{
$this->expectException(Serializer\Exception\NotNormalizableValueException::class);

$this->subject->denormalize(null, Sitemap\ChangeFrequency::class);
}

/**
* @test
*/
public function denormalizeThrowsExceptionIfGivenDataCannotBeDenormalized(): void
{
$this->expectException(Serializer\Exception\NotNormalizableValueException::class);

$this->subject->denormalize('foo', Sitemap\ChangeFrequency::class);
}

/**
* @test
*
* @dataProvider denormalizeReturnsDenormalizedDataDataProvider
*/
public function denormalizeReturnsDenormalizedData(string $data, Sitemap\ChangeFrequency $expected): void
{
self::assertSame($expected, $this->subject->denormalize($data, Sitemap\ChangeFrequency::class));
}

/**
* @test
*/
public function supportsDenormalizationReturnsTrueIfGivenTypeIsChangeFrequency(): void
{
self::assertTrue($this->subject->supportsDenormalization('foo', Sitemap\ChangeFrequency::class));
self::assertFalse($this->subject->supportsDenormalization('foo', 'baz'));
}

/**
* @return Generator<string, array{string, Sitemap\ChangeFrequency}>
*/
public function denormalizeReturnsDenormalizedDataDataProvider(): Generator
{
yield 'supported value' => ['monthly', Sitemap\ChangeFrequency::Monthly];
yield 'case-insensitive value' => ['Monthly', Sitemap\ChangeFrequency::Monthly];
}
}

0 comments on commit 475dce7

Please sign in to comment.