Skip to content

Commit ad1c9b4

Browse files
committed
Place entries in structure when localizing. Fixes #2471
1 parent 4c33f8f commit ad1c9b4

File tree

2 files changed

+154
-0
lines changed

2 files changed

+154
-0
lines changed

src/Http/Controllers/CP/Collections/LocalizeEntryController.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,39 @@ public function __invoke(Request $request, $collection, $entry)
1414

1515
$localized = $entry->makeLocalization($site = $request->site);
1616

17+
$this->addToStructure($collection, $entry, $localized);
18+
1719
$localized->store(['user' => User::fromUser($request->user())]);
1820

1921
return [
2022
'handle' => $site,
2123
'url' => $localized->editUrl(),
2224
];
2325
}
26+
27+
private function addToStructure($collection, $entry, $localized)
28+
{
29+
// If it's orderable (linear - a max depth of 1) then don't add it.
30+
if ($collection->orderable()) {
31+
return;
32+
}
33+
34+
// Collection not structured? Don't add it.
35+
if (! $structure = $collection->structure()) {
36+
return;
37+
}
38+
39+
$tree = $structure->in($localized->locale());
40+
$parent = $entry->parent()->in($localized->locale());
41+
42+
$localized->afterSave(function ($localized) use ($parent, $tree) {
43+
if (! $parent || $parent->isRoot()) {
44+
$tree->append($localized);
45+
} else {
46+
$tree->appendTo($parent->id(), $localized);
47+
}
48+
49+
$tree->save();
50+
});
51+
}
2452
}

tests/Feature/Entries/LocalizeEntryTest.php

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Tests\Feature\Entries;
44

55
use Facades\Tests\Factories\EntryFactory;
6+
use Statamic\Facades\Collection;
67
use Statamic\Facades\Site;
78
use Statamic\Facades\User;
89
use Tests\FakesRoles;
@@ -60,6 +61,131 @@ public function site_is_required()
6061
->assertSessionHasErrors('site');
6162
}
6263

64+
/** @test */
65+
public function it_adds_an_entry_to_the_structure_tree_if_its_nested()
66+
{
67+
$collection = tap(Collection::make('pages')->sites(['en', 'fr']))->save();
68+
$enHome = EntryFactory::collection($collection)->slug('home')->locale('en')->id('home')->create();
69+
$fnHome = EntryFactory::collection($collection)->slug('home')->locale('fr')->id('fr-home')->origin('home')->create();
70+
$enAbout = EntryFactory::collection($collection)->slug('about')->locale('en')->id('about')->create();
71+
$frAbout = EntryFactory::collection($collection)->slug('about')->locale('fr')->id('fr-about')->origin('about')->create();
72+
$enTeam = EntryFactory::collection($collection)->slug('team')->locale('en')->id('team')->create();
73+
$this->assertNull($enTeam->in('fr'));
74+
$collection->structureContents(['root' => true, 'tree' => [
75+
'en' => [
76+
['entry' => 'home'],
77+
['entry' => 'about', 'children' => [
78+
['entry' => 'team'],
79+
]],
80+
],
81+
'fr' => [
82+
['entry' => 'fr-home'],
83+
['entry' => 'fr-about'],
84+
],
85+
]])->save();
86+
87+
$this->assertEquals([
88+
['entry' => 'fr-home'],
89+
['entry' => 'fr-about'],
90+
], Collection::findByHandle('pages')->structure()->in('fr')->tree());
91+
92+
$this
93+
->actingAs($this->user())
94+
->localize($enTeam, ['site' => 'fr'])
95+
->assertOk();
96+
97+
$frTeam = $enTeam->fresh()->in('fr');
98+
$this->assertNotNull($frTeam);
99+
100+
$this->assertEquals([
101+
['entry' => 'fr-home'],
102+
['entry' => 'fr-about', 'children' => [
103+
['entry' => $frTeam->id()],
104+
]],
105+
], Collection::findByHandle('pages')->structure()->in('fr')->tree());
106+
}
107+
108+
/** @test */
109+
public function it_adds_an_entry_to_the_end_of_the_structure_tree_if_the_parent_is_the_root()
110+
{
111+
$collection = tap(Collection::make('pages')->sites(['en', 'fr']))->save();
112+
$enHome = EntryFactory::collection($collection)->slug('home')->locale('en')->id('home')->create();
113+
$fnHome = EntryFactory::collection($collection)->slug('home')->locale('fr')->id('fr-home')->origin('home')->create();
114+
$enAbout = EntryFactory::collection($collection)->slug('about')->locale('en')->id('about')->create();
115+
$frAbout = EntryFactory::collection($collection)->slug('about')->locale('fr')->id('fr-about')->origin('about')->create();
116+
$enTeam = EntryFactory::collection($collection)->slug('team')->locale('en')->id('team')->create();
117+
$this->assertNull($enTeam->in('fr'));
118+
$collection->structureContents(['root' => true, 'tree' => [
119+
'en' => [
120+
['entry' => 'home'],
121+
['entry' => 'about'],
122+
['entry' => 'team'],
123+
],
124+
'fr' => [
125+
['entry' => 'fr-home'],
126+
['entry' => 'fr-about'],
127+
],
128+
]])->save();
129+
130+
$this->assertEquals([
131+
['entry' => 'fr-home'],
132+
['entry' => 'fr-about'],
133+
], Collection::findByHandle('pages')->structure()->in('fr')->tree());
134+
135+
$this
136+
->actingAs($this->user())
137+
->localize($enTeam, ['site' => 'fr'])
138+
->assertOk();
139+
140+
$frTeam = $enTeam->fresh()->in('fr');
141+
$this->assertNotNull($frTeam);
142+
143+
$this->assertEquals([
144+
['entry' => 'fr-home'],
145+
['entry' => 'fr-about'],
146+
['entry' => $frTeam->id()],
147+
], Collection::findByHandle('pages')->structure()->in('fr')->tree());
148+
}
149+
150+
/** @test */
151+
public function it_adds_an_entry_to_the_end_of_the_structure_tree_if_the_parent_doesnt_exist_in_that_site()
152+
{
153+
$collection = tap(Collection::make('pages')->sites(['en', 'fr']))->save();
154+
$enHome = EntryFactory::collection($collection)->slug('home')->locale('en')->id('home')->create();
155+
$fnHome = EntryFactory::collection($collection)->slug('home')->locale('fr')->id('fr-home')->origin('home')->create();
156+
$enAbout = EntryFactory::collection($collection)->slug('about')->locale('en')->id('about')->create();
157+
$enTeam = EntryFactory::collection($collection)->slug('team')->locale('en')->id('team')->create();
158+
$this->assertNull($enTeam->in('fr'));
159+
$collection->structureContents(['root' => true, 'tree' => [
160+
'en' => [
161+
['entry' => 'home'],
162+
['entry' => 'about', 'children' => [
163+
['entry' => 'team'],
164+
]],
165+
],
166+
'fr' => [
167+
['entry' => 'fr-home'],
168+
],
169+
]])->save();
170+
171+
$this->assertEquals([
172+
['entry' => 'fr-home'],
173+
], Collection::findByHandle('pages')->structure()->in('fr')->tree());
174+
175+
$this
176+
->actingAs($this->user())
177+
->localize($enTeam, ['site' => 'fr'])
178+
->assertOk();
179+
180+
$frTeam = $enTeam->fresh()->in('fr');
181+
$this->assertNotNull($frTeam);
182+
183+
$this->assertEquals([
184+
['entry' => 'fr-home'],
185+
['entry' => $frTeam->id()],
186+
], Collection::findByHandle('pages')->structure()->in('fr')->tree());
187+
}
188+
63189
private function localize($entry, $params = [])
64190
{
65191
$url = cp_route('collections.entries.localize', [

0 commit comments

Comments
 (0)