Skip to content

Commit 8e91788

Browse files
committed
Allow passing a closure to Route::localizedUrl()
1 parent 514cab0 commit 8e91788

File tree

3 files changed

+72
-11
lines changed

3 files changed

+72
-11
lines changed

src/Macros/LocalizedUrlMacro.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ class LocalizedUrlMacro
1616
public static function register()
1717
{
1818
Route::macro('localizedUrl', function ($locale = null, $parameters = null, $absolute = true) {
19-
if ( ! $parameters) {
20-
$parameters = Route::current()->parameters();
21-
$model = Collection::make($parameters)->first();
19+
$parameters = $parameters ?: Route::current()->parameters();
20+
$model = Collection::make($parameters)->first();
2221

23-
if ($model instanceof ProvidesRouteParameters) {
24-
$parameters = $model->getRouteParameters($locale);
25-
}
22+
if ($model instanceof ProvidesRouteParameters) {
23+
$parameters = $model->getRouteParameters($locale);
24+
}
25+
26+
if (is_callable($parameters)) {
27+
$parameters = $parameters($locale);
2628
}
2729

2830
return route(Route::currentRouteName(), $parameters, $absolute, $locale);

tests/Stubs/Model.php

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,41 @@ class Model extends BaseModel
1616
*/
1717
protected function getSlugAttribute()
1818
{
19-
return $this->attributes['slug'][App::getLocale()];
19+
return $this->getSlug();
20+
}
21+
22+
/**
23+
* Get the localized slug.
24+
*
25+
* @param string|null $locale
26+
*
27+
* @return string
28+
*/
29+
public function getSlug($locale = null)
30+
{
31+
return $this->attributes['slug'][$locale ?: App::getLocale()];
2032
}
2133

2234
/**
2335
* Fake route model binding.
2436
*
25-
* @param string $slug
37+
* @param string $parameter
2638
*
2739
* @return mixed
2840
*/
29-
public function resolveRouteBinding($slug)
41+
public function resolveRouteBinding($parameter)
3042
{
43+
// Bypass the database for testing purpose and return
44+
// the current model as if it was found in the database.
45+
if ($this->getRouteKeyName() === 'id') {
46+
return $this;
47+
}
48+
49+
// If the parameter is a slug, check if it is in the right language
50+
// and return the current model as if it was found in the database.
3151
$validSlug = $this->attributes['slug'][App::getLocale()];
3252

33-
if ($validSlug !== $slug) {
53+
if ($validSlug !== $parameter) {
3454
abort(404);
3555
}
3656

tests/Unit/Macros/CurrentUrlMacroTest.php

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public function it_cannot_guess_a_localized_route_key_without_route_model_bindin
111111
}
112112

113113
/** @test */
114-
public function you_can_pass_it_a_model_with_a_localized_route_key()
114+
public function you_can_pass_it_a_model_with_a_localized_route_key_without_route_model_binding()
115115
{
116116
$this->setSupportedLocales(['en', 'nl']);
117117

@@ -142,4 +142,43 @@ public function you_can_pass_it_a_model_with_a_localized_route_key()
142142
'nl' => url('/nl/route/nl-slug'),
143143
], $response->original);
144144
}
145+
146+
/** @test */
147+
public function you_can_pass_it_a_closure_that_returns_the_parameters_without_route_model_binding()
148+
{
149+
$this->setSupportedLocales(['en', 'nl']);
150+
151+
$model = (new Model([
152+
'id' => 1,
153+
'slug' => [
154+
'en' => 'en-slug',
155+
'nl' => 'nl-slug',
156+
],
157+
]))->setKeyName('id');
158+
159+
App::instance(Model::class, $model);
160+
161+
Route::localized(function () use ($model) {
162+
Route::get('route/{id}/{slug}', function ($id, $slug) use ($model) {
163+
164+
$closure = function ($locale) use ($model) {
165+
return [$model->id, $model->getSlug($locale)];
166+
};
167+
168+
return [
169+
'current' => Route::localizedUrl(),
170+
'en' => Route::localizedUrl('en', $closure),
171+
'nl' => Route::localizedUrl('nl', $closure),
172+
];
173+
});
174+
});
175+
176+
$response = $this->call('GET', '/en/route/1/en-slug');
177+
$response->assertOk();
178+
$this->assertEquals([
179+
'current' => url('/en/route/1/en-slug'),
180+
'en' => url('/en/route/1/en-slug'),
181+
'nl' => url('/nl/route/1/nl-slug'),
182+
], $response->original);
183+
}
145184
}

0 commit comments

Comments
 (0)