diff --git a/src/Structures/AugmentedPage.php b/src/Structures/AugmentedPage.php index 5a91172fbd1..76dfb541e74 100644 --- a/src/Structures/AugmentedPage.php +++ b/src/Structures/AugmentedPage.php @@ -61,6 +61,16 @@ protected function getFromData($key) return $this->page->getSupplement($key) ?? $this->page->value($key); } + protected function url() + { + return $this->page->url(); + } + + protected function urlWithoutRedirect() + { + return $this->page->urlWithoutRedirect(); + } + public function blueprintFields() { if ($this->fieldsCache) { diff --git a/src/Structures/Page.php b/src/Structures/Page.php index 207d3eeeead..6b372b0eba0 100644 --- a/src/Structures/Page.php +++ b/src/Structures/Page.php @@ -79,12 +79,37 @@ public function setUrl($url) public function url() { - return $this->url ?? optional($this->entry())->url(); + if ($this->url) { + return $this->url; + } + + if (! $entry = $this->entry()) { + return null; + } + + return $this->linksToAnotherSite($entry) ? $entry->absoluteUrl() : $entry->url(); } public function urlWithoutRedirect() { - return $this->url ?? optional($this->entry())->urlWithoutRedirect(); + if ($this->url) { + return $this->url; + } + + if (! $entry = $this->entry()) { + return null; + } + + return $this->linksToAnotherSite($entry) ? $entry->absoluteUrlWithoutRedirect() : $entry->urlWithoutRedirect(); + } + + private function linksToAnotherSite(Entry $entry) + { + if (! $this->structure() instanceof Nav || ! $this->structure()->canSelectAcrossSites()) { + return false; + } + + return $entry->site()->handle() !== $this->tree->site()->handle(); } public function isRedirect() diff --git a/tests/Data/Structures/AugmentedPageTest.php b/tests/Data/Structures/AugmentedPageTest.php index 39e2e863bf4..30c3bfebe9c 100644 --- a/tests/Data/Structures/AugmentedPageTest.php +++ b/tests/Data/Structures/AugmentedPageTest.php @@ -200,6 +200,7 @@ public function it_gets_values_from_the_entry() $page->shouldReceive('data')->andReturn(collect(['one' => 'dos', 'three' => 'quatro', 'five' => 'seis'])); $page->shouldReceive('supplements')->andReturn(collect(['seven' => 'ocho'])); $page->shouldReceive('title')->andReturn('The Page Title'); + $page->shouldReceive('url')->andReturn('/the-url'); $page->shouldReceive('value')->with('one')->andReturn('dos'); $page->shouldReceive('value')->with('three')->andReturn('quatro'); $page->shouldReceive('value')->with('five')->andReturn('seis'); diff --git a/tests/Data/Structures/PageTest.php b/tests/Data/Structures/PageTest.php index 83d42d3a630..63cd7d1b2ca 100644 --- a/tests/Data/Structures/PageTest.php +++ b/tests/Data/Structures/PageTest.php @@ -243,9 +243,10 @@ public function it_gets_the_entrys_uri_when_the_structure_does_not_have_a_collec $entry->shouldReceive('uri')->andReturn('/the/actual/entry/uri'); $entry->shouldReceive('value')->with('redirect')->andReturnNull(); - $tree = $this->newTree()->setStructure( - $this->mock(Nav::class) - ); + $nav = $this->mock(Nav::class); + $nav->shouldReceive('canSelectAcrossSites')->andReturnFalse(); + + $tree = $this->newTree()->setStructure($nav); $page = (new Page) ->setTree($tree) @@ -269,9 +270,10 @@ public function it_gets_the_uri_of_a_redirect_entry() $entry->shouldReceive('uri')->andReturn('/the/actual/entry/uri'); $entry->shouldReceive('value')->with('redirect')->andReturn('http://example.com/page'); - $tree = $this->newTree()->setStructure( - $this->mock(Nav::class) - ); + $nav = $this->mock(Nav::class); + $nav->shouldReceive('canSelectAcrossSites')->andReturnFalse(); + + $tree = $this->newTree()->setStructure($nav); $page = (new Page) ->setTree($tree) diff --git a/tests/Tags/StructureTagTest.php b/tests/Tags/StructureTagTest.php index 1c23d02ef9d..747540a1211 100644 --- a/tests/Tags/StructureTagTest.php +++ b/tests/Tags/StructureTagTest.php @@ -9,6 +9,7 @@ use Statamic\Facades\Collection; use Statamic\Facades\Entry; use Statamic\Facades\Nav; +use Statamic\Facades\Site; use Tests\PreventSavingStacheItemsToDisk; use Tests\TestCase; @@ -455,6 +456,52 @@ public function it_sets_is_current_and_is_parent_for_a_nav_when_home_is_an_entry $this->assertEquals('[home][1=parent][1-1=parent][1-1-1=current][1-1-1-1][2][3]', $result); } + #[Test] + public function it_uses_the_absolute_url_for_a_nav_entry_link_on_another_site() + { + $this->makeCrossSiteNav(); + + $template = '{{ nav:test }}[{{ id }}={{ url }}]{{ /nav:test }}'; + + $this->assertEquals('[link=http://two.example.com/projects][local-link=/projects]', (string) Antlers::parse($template, [], true)); + } + + #[Test] + public function it_only_flags_the_local_nav_entry_link_as_current() + { + $this->makeCrossSiteNav(); + + $mock = \Mockery::mock(\Statamic\Facades\URL::getFacadeRoot())->makePartial(); + \Statamic\Facades\URL::swap($mock); + $mock->shouldReceive('getCurrent')->once()->andReturn('/projects'); + + $template = '{{ nav:test }}[{{ id }}{{ if is_current }}=current{{ /if }}]{{ /nav:test }}'; + + $this->assertEquals('[link][local-link=current]', (string) Antlers::parse($template, [], true)); + } + + private function makeCrossSiteNav() + { + $this->setSites([ + 'en' => ['url' => 'http://one.example.com/', 'locale' => 'en'], + 'fr' => ['url' => 'http://two.example.com/', 'locale' => 'fr'], + ]); + + Site::setCurrent('en'); + + tap(Collection::make('pages')->routes('{slug}'))->sites(['en', 'fr'])->save(); + + EntryFactory::collection('pages')->id('projects')->locale('en')->slug('projects')->data(['title' => 'Projects'])->create(); + EntryFactory::collection('pages')->id('projects-fr')->origin('projects')->locale('fr')->slug('projects')->data(['title' => 'Projects'])->create(); + + $nav = Nav::make('test')->canSelectAcrossSites(true); + $nav->makeTree('en', [ + ['id' => 'link', 'title' => 'Projects', 'entry' => 'projects-fr'], + ['id' => 'local-link', 'title' => 'Projects (local)', 'entry' => 'projects'], + ])->save(); + $nav->save(); + } + #[Test] public function it_sets_is_parent_based_on_the_url_too() {