core icon indicating copy to clipboard operation
core copied to clipboard

[v3][UuidUriVariableTransformer] Harden the supports method of the Uuid transformer

Open silverbackdan opened this issue 2 years ago • 3 comments

Description
I have a resource in API Platform v2 called routes and I have it setup so that I can call /routes/[uuid_here] or routes/[path_here] where uuid would be a regular UUID but I also wanted to use paths such as /contact resulting in a full resource path /routes//contact

Before I could just do this, set my ID URI variable requirements and then handle everything in a custom data provider. So I have created the same as a new Sate Provider and it is here where I would use the string which may be a path or UUID to first lookup the resource by Path, before creating a UUID from the string if that failed to find a result and then lookup the result again.

If the supportsTransformation method detected whether the string was an actual UUID first then I could get past this.

Additionally, if there was a way to configure not to use the data transformer on a per route level, then perhaps I could disable this transformer...

For now I think I may have to decorate the transformer to disable it perhaps when I am not using a UUID..

Any thoughts on a better approach for me to get the result I'm after in v3 - or perhaps just a better practice/approach.

TIA.

silverbackdan avatar Apr 02 '22 20:04 silverbackdan

For my needs I've currently just decorated like this

<?php

declare(strict_types=1);

namespace Silverback\ApiComponentsBundle\RamseyUuid\UuidUriVariableTransformer;

use ApiPlatform\Api\UriVariableTransformerInterface;
use ApiPlatform\Exception\InvalidUriVariableException;
use ApiPlatform\RamseyUuid\UriVariableTransformer\UuidUriVariableTransformer as BaseUuidUriVariableTransformer;

/**
 * @author Daniel West <[email protected]>
 */
class UuidUriVariableTransformer implements UriVariableTransformerInterface
{
    private BaseUuidUriVariableTransformer $decorated;

    public function __construct(BaseUuidUriVariableTransformer $decorated)
    {
        $this->decorated = $decorated;
    }

    public function transform($value, array $types, array $context = [])
    {
        try {
            return $this->decorated->transform($value, $types, $context);
        } catch (InvalidUriVariableException $exception) {
            return $value;
        }
    }

    public function supportsTransformation($value, array $types, array $context = []): bool
    {
        return $this->decorated->supportsTransformation($value, $types, $context);
    }
}

Perhaps we could work out a context where we could fallback to the original value if the UUID fails?

silverbackdan avatar Apr 02 '22 20:04 silverbackdan

I feel this is way too specific for us to add a condition to return the original value if the uuid fails no?

soyuka avatar Apr 05 '22 07:04 soyuka

Possibly, I've just decorated it in my bundle for now, but I wonder if a dev may want to be able to use an identifier or another field, and if they do, they'll come across this error. I suppose the question is, if the ID isn't a UUID, is the best course of action to continue trying or to fail and throw the exception. If we failover I think we'd get a 404 instead of a server error.

(I think it was throwing a server error, I'd have to double check)

silverbackdan avatar Apr 05 '22 20:04 silverbackdan

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Nov 04 '22 21:11 stale[bot]

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jan 03 '23 23:01 stale[bot]