Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/Schema/Resource.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ class Resource implements \JsonSerializable
private const RESOURCE_NAME_PATTERN = '/^[a-zA-Z0-9_-]+$/';

/**
* URI pattern regex - requires a valid scheme, followed by colon and optional path.
* Example patterns: config://, file://path, db://table, etc.
* URI pattern regex - requires a valid scheme followed by colon and optional path (RFC 3986).
* Example patterns: file://path, db://table, urn:isbn:123, config:key, etc.
*/
private const URI_PATTERN = '/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/[^\s]*$/';
private const URI_PATTERN = '/^[a-zA-Z][a-zA-Z0-9+.-]*:[^\s]*$/';

/**
* @param string $uri the URI of this resource
Expand Down
6 changes: 3 additions & 3 deletions src/Schema/ResourceTemplate.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ class ResourceTemplate implements \JsonSerializable
private const RESOURCE_NAME_PATTERN = '/^[a-zA-Z0-9_-]+$/';

/**
* URI Template pattern regex - requires a valid scheme, followed by colon and path with at least one placeholder.
* Example patterns: config://{key}, file://{path}/contents.txt, db://{table}/{id}, etc.
* URI Template pattern regex - requires a valid scheme followed by colon and path with at least one placeholder (RFC 3986).
* Example patterns: file://{path}/contents.txt, db://{table}/{id}, config:{key}, etc.
*/
private const URI_TEMPLATE_PATTERN = '/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\/.*{[^{}]+}.*/';
private const URI_TEMPLATE_PATTERN = '/^[a-zA-Z][a-zA-Z0-9+.-]*:.*{[^{}]+}.*/';

/**
* @param string $uriTemplate a URI template (according to RFC 6570) that can be used to construct resource URIs
Expand Down
19 changes: 19 additions & 0 deletions tests/Unit/Schema/ResourceTemplateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,25 @@ public function testConstructorInvalid(): void
);
}

#[DataProvider('provideValidTemplatesWithoutDoubleSlash')]
public function testConstructorAcceptsTemplatesWithoutDoubleSlash(string $uriTemplate): void
{
$resource = new ResourceTemplate(
uriTemplate: $uriTemplate,
name: 'test-template',
);

$this->assertInstanceOf(ResourceTemplate::class, $resource);
$this->assertSame($uriTemplate, $resource->uriTemplate);
}

public static function provideValidTemplatesWithoutDoubleSlash(): iterable
Comment thread
chr-hertel marked this conversation as resolved.
Outdated
{
yield 'custom scheme without slashes' => ['config:{key}'];
yield 'custom scheme with slashes' => ['config://{key}'];
yield 'urn-style template' => ['urn:resource:{id}'];
}

public function testFromArrayValid(): void
{
$resource = ResourceTemplate::fromArray([
Expand Down
21 changes: 21 additions & 0 deletions tests/Unit/Schema/ResourceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,27 @@ public function testConstructorInvalid(): void
);
}

#[DataProvider('provideValidUrisWithoutDoubleSlash')]
public function testConstructorAcceptsUrisWithoutDoubleSlash(string $uri): void
{
$resource = new Resource(
uri: $uri,
name: 'test-resource',
);

$this->assertInstanceOf(Resource::class, $resource);
$this->assertSame($uri, $resource->uri);
}

public static function provideValidUrisWithoutDoubleSlash(): iterable
Comment thread
chr-hertel marked this conversation as resolved.
Outdated
{
yield 'urn' => ['urn:isbn:0451450523'];
yield 'mailto' => ['mailto:user@example.com'];
yield 'data' => ['data:text/plain;base64,SGVsbG8='];
yield 'custom scheme without slashes' => ['config:myapp/settings'];
yield 'custom scheme with slashes' => ['config://myapp/settings'];
}

public function testFromArrayValid(): void
{
$resource = Resource::fromArray([
Expand Down