Scaffold MediaUrlResolver with null fallback
Initial skeleton returning null for any non-media URL. Subsequent commits add detection for video, audio, YouTube, and Vimeo. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Markdown;
|
||||||
|
|
||||||
|
class MediaUrlResolver
|
||||||
|
{
|
||||||
|
public function resolve(string $url): ?string
|
||||||
|
{
|
||||||
|
if ($url === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Unit\Markdown;
|
||||||
|
|
||||||
|
use App\Markdown\MediaUrlResolver;
|
||||||
|
use PHPUnit\Framework\Attributes\DataProvider;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class MediaUrlResolverTest extends TestCase
|
||||||
|
{
|
||||||
|
private MediaUrlResolver $resolver;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
$this->resolver = new MediaUrlResolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[DataProvider('nonMediaUrls')]
|
||||||
|
public function test_returns_null_for_non_media_urls(string $url): void
|
||||||
|
{
|
||||||
|
$this->assertNull($this->resolver->resolve($url));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function nonMediaUrls(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'normal image' => ['/photo.jpg'],
|
||||||
|
'svg' => ['/icon.svg'],
|
||||||
|
'png' => ['/avatar.png'],
|
||||||
|
'no extension' => ['/foo'],
|
||||||
|
'empty string' => [''],
|
||||||
|
'javascript scheme' => ['javascript:alert(1)'],
|
||||||
|
'host-only' => ['http://'],
|
||||||
|
'youtu.be lookalike host' => ['https://example.com/youtu.be-fake/abc'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user