Skip to content

Commit 8db2554

Browse files
miicahjasonvarga
andauthored
[5.x] Allow statamic URLs to use fragments or query strings (#13085)
Co-authored-by: Jason Varga <jason@pixelfear.com>
1 parent 30d3df4 commit 8db2554

2 files changed

Lines changed: 139 additions & 3 deletions

File tree

src/Fieldtypes/Concerns/ResolvesStatamicUrls.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ trait ResolvesStatamicUrls
1313
*/
1414
protected function resolveStatamicUrls(string $content)
1515
{
16-
return preg_replace_callback('/([("])statamic:\/\/([^()"]*)([)"])/im', function ($matches) {
16+
return preg_replace_callback('/([("])statamic:\/\/([^()"?#]*)([^()"]*)([)"])/im', function ($matches) {
1717
$data = Data::find($matches[2]);
18-
$url = $data ? $data->url() : '';
18+
$url = $data ? $data->url().$matches[3] : '';
1919

20-
return $matches[1].$url.$matches[3];
20+
return $matches[1].$url.$matches[4];
2121
}, $content);
2222
}
2323
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<?php
2+
3+
namespace Tests\Fieldtypes\Concerns;
4+
5+
use Mockery;
6+
use PHPUnit\Framework\Attributes\Test;
7+
use Statamic\Facades\Data as DataFacade;
8+
use Statamic\Fieldtypes\Concerns\ResolvesStatamicUrls;
9+
use Tests\TestCase;
10+
11+
class ResolvesStatamicUrlsTest extends TestCase
12+
{
13+
private $testClass;
14+
15+
public function setUp(): void
16+
{
17+
parent::setUp();
18+
19+
$this->testClass = new class
20+
{
21+
use ResolvesStatamicUrls;
22+
23+
public function resolve(string $content)
24+
{
25+
return $this->resolveStatamicUrls($content);
26+
}
27+
};
28+
}
29+
30+
#[Test]
31+
public function it_calls_data_find_with_correct_id()
32+
{
33+
$data = Mockery::mock();
34+
$data->shouldReceive('url')->andReturn('/some/url');
35+
36+
DataFacade::shouldReceive('find')
37+
->once()
38+
->with('foo::bar/baz.ext')
39+
->andReturn($data);
40+
41+
$content = '[link](statamic://foo::bar/baz.ext)';
42+
$result = $this->testClass->resolve($content);
43+
44+
$this->assertEquals('[link](/some/url)', $result);
45+
}
46+
47+
#[Test]
48+
public function it_handles_non_existent_data()
49+
{
50+
DataFacade::shouldReceive('find')
51+
->once()
52+
->with('non-existent')
53+
->andReturn(null);
54+
55+
$content = '[link](statamic://non-existent)';
56+
$result = $this->testClass->resolve($content);
57+
58+
$this->assertEquals('[link]()', $result);
59+
}
60+
61+
#[Test]
62+
public function it_handles_multiple_urls()
63+
{
64+
$data1 = Mockery::mock();
65+
$data1->shouldReceive('url')->andReturn('/url-1');
66+
67+
$data2 = Mockery::mock();
68+
$data2->shouldReceive('url')->andReturn('/url-2');
69+
70+
DataFacade::shouldReceive('find')
71+
->once()
72+
->with('id-1')
73+
->andReturn($data1);
74+
75+
DataFacade::shouldReceive('find')
76+
->once()
77+
->with('id-2')
78+
->andReturn($data2);
79+
80+
$content = '[link1](statamic://id-1) and <img src="statamic://id-2" />';
81+
$result = $this->testClass->resolve($content);
82+
83+
$this->assertEquals('[link1](/url-1) and <img src="/url-2" />', $result);
84+
}
85+
86+
#[Test]
87+
public function it_maintains_hash_fragments()
88+
{
89+
$data = Mockery::mock();
90+
$data->shouldReceive('url')->andReturn('/some/page');
91+
92+
DataFacade::shouldReceive('find')
93+
->once()
94+
->with('entry::123')
95+
->andReturn($data);
96+
97+
$content = '[link](statamic://entry::123#section)';
98+
$result = $this->testClass->resolve($content);
99+
100+
$this->assertEquals('[link](/some/page#section)', $result);
101+
}
102+
103+
#[Test]
104+
public function it_maintains_query_strings()
105+
{
106+
$data = Mockery::mock();
107+
$data->shouldReceive('url')->andReturn('/some/page');
108+
109+
DataFacade::shouldReceive('find')
110+
->once()
111+
->with('entry::123')
112+
->andReturn($data);
113+
114+
$content = '[link](statamic://entry::123?foo=bar)';
115+
$result = $this->testClass->resolve($content);
116+
117+
$this->assertEquals('[link](/some/page?foo=bar)', $result);
118+
}
119+
120+
#[Test]
121+
public function it_maintains_query_strings_and_hash_fragments()
122+
{
123+
$data = Mockery::mock();
124+
$data->shouldReceive('url')->andReturn('/some/page');
125+
126+
DataFacade::shouldReceive('find')
127+
->once()
128+
->with('entry::123')
129+
->andReturn($data);
130+
131+
$content = '[link](statamic://entry::123?foo=bar#section)';
132+
$result = $this->testClass->resolve($content);
133+
134+
$this->assertEquals('[link](/some/page?foo=bar#section)', $result);
135+
}
136+
}

0 commit comments

Comments
 (0)