Skip to content

Commit d1b0af1

Browse files
authored
Add ability to generate current localized url while using two different models in route model binding (#55)
1 parent 0ad85b4 commit d1b0af1

File tree

5 files changed

+145
-21
lines changed

5 files changed

+145
-21
lines changed

src/LocalizedUrlGenerator.php

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
namespace CodeZero\LocalizedRoutes;
44

5-
use Illuminate\Contracts\Routing\UrlRoutable;
5+
use InvalidArgumentException;
66
use Illuminate\Support\Collection;
77
use Illuminate\Support\Facades\App;
8+
use Illuminate\Support\Facades\Route;
89
use Illuminate\Support\Facades\Config;
910
use Illuminate\Support\Facades\Request;
10-
use Illuminate\Support\Facades\Route;
11-
use InvalidArgumentException;
11+
use Illuminate\Contracts\Routing\UrlRoutable;
1212

1313
class LocalizedUrlGenerator
1414
{
@@ -49,7 +49,7 @@ public function generateFromRequest($locale = null, $parameters = null, $absolut
4949
$urlBuilder = UrlBuilder::make(Request::fullUrl());
5050
$locale = $locale ?: $this->detectLocale($urlBuilder);
5151

52-
if ( ! $this->is404()) {
52+
if (!$this->is404()) {
5353
// $parameters can be an array, a function or it can contain model instances!
5454
// Normalize the parameters so we end up with an array of key => value pairs.
5555
$parameters = $this->prepareParameters($locale, $parameters ?: $this->getRouteParameters());
@@ -71,7 +71,7 @@ public function generateFromRequest($locale = null, $parameters = null, $absolut
7171

7272
// If custom domains are not used and it is not a registered,
7373
// non localized route, update the locale slug in the path.
74-
if ( ! $this->hasCustomDomains() && ($this->is404() || $this->isLocalized())) {
74+
if (!$this->hasCustomDomains() && ($this->is404() || $this->isLocalized())) {
7575
$urlBuilder->setSlugs($this->updateLocaleInSlugs($urlBuilder->getSlugs(), $locale));
7676
}
7777

@@ -117,7 +117,7 @@ public function isLocalized()
117117
*/
118118
protected function is404()
119119
{
120-
return ! $this->routeExists() || $this->isFallback();
120+
return !$this->routeExists() || $this->isFallback();
121121
}
122122

123123
/**
@@ -358,10 +358,14 @@ protected function replaceParameters($uri, $parameters)
358358
*/
359359
protected function prepareParameters($locale, $parameters)
360360
{
361-
$model = Collection::make($parameters)->first();
362-
363-
if ($model instanceof ProvidesRouteParameters) {
364-
$parameters = $model->getRouteParameters($locale);
361+
$models = Collection::make($parameters)->filter(function ($model) {
362+
return $model instanceof ProvidesRouteParameters;
363+
});
364+
365+
if ($models->count()) {
366+
$parameters = $models->flatMap(function ($model) use ($locale) {
367+
return $model->getRouteParameters($locale);
368+
})->all();
365369
}
366370

367371
if (is_callable($parameters)) {

tests/Stubs/ModelBar.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace CodeZero\LocalizedRoutes\Tests\Stubs;
4+
5+
use Illuminate\Support\Facades\App;
6+
use Illuminate\Database\Eloquent\Model as BaseModel;
7+
use CodeZero\LocalizedRoutes\ProvidesRouteParameters;
8+
9+
class ModelBar extends BaseModel implements ProvidesRouteParameters
10+
{
11+
protected $guarded = [];
12+
13+
/**
14+
* Get the route parameters for this model.
15+
*
16+
* @param string|null $locale
17+
*
18+
* @return array
19+
*/
20+
public function getRouteParameters($locale = null)
21+
{
22+
return [
23+
$this->attributes['slug'][$locale ?: App::getLocale()]
24+
];
25+
}
26+
27+
/**
28+
* Fake route model binding (avoid database for test purpose).
29+
*
30+
* @param int $id
31+
* @param string|null $field
32+
*
33+
* @return mixed
34+
*/
35+
public function resolveRouteBinding($id, $field = null)
36+
{
37+
return $this;
38+
}
39+
}

tests/Stubs/ModelFoo.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace CodeZero\LocalizedRoutes\Tests\Stubs;
4+
5+
use Illuminate\Support\Facades\App;
6+
use Illuminate\Database\Eloquent\Model as BaseModel;
7+
use CodeZero\LocalizedRoutes\ProvidesRouteParameters;
8+
9+
class ModelFoo extends BaseModel implements ProvidesRouteParameters
10+
{
11+
protected $guarded = [];
12+
13+
/**
14+
* Get the route parameters for this model.
15+
*
16+
* @param string|null $locale
17+
*
18+
* @return array
19+
*/
20+
public function getRouteParameters($locale = null)
21+
{
22+
return [
23+
$this->attributes['slug'][$locale ?: App::getLocale()]
24+
];
25+
}
26+
27+
/**
28+
* Fake route model binding (avoid database for test purpose).
29+
*
30+
* @param int $id
31+
* @param string|null $field
32+
*
33+
* @return mixed
34+
*/
35+
public function resolveRouteBinding($id, $field = null)
36+
{
37+
return $this;
38+
}
39+
}

tests/Unit/Macros/LocalizedUrlMacroTest.php

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@
22

33
namespace CodeZero\LocalizedRoutes\Tests\Unit\Macros;
44

5-
use CodeZero\LocalizedRoutes\Middleware\SetLocale;
6-
use CodeZero\LocalizedRoutes\Tests\Stubs\Model;
7-
use CodeZero\LocalizedRoutes\Tests\Stubs\ModelWithCustomRouteParameters;
8-
use CodeZero\LocalizedRoutes\Tests\TestCase;
9-
use Illuminate\Database\Eloquent\ModelNotFoundException;
105
use Illuminate\Support\Facades\App;
11-
use Illuminate\Support\Facades\Config;
126
use Illuminate\Support\Facades\Lang;
13-
use Illuminate\Support\Facades\Route;
147
use Illuminate\Support\Facades\View;
8+
use Illuminate\Support\Facades\Route;
9+
use Illuminate\Support\Facades\Config;
10+
use CodeZero\LocalizedRoutes\Tests\TestCase;
11+
use CodeZero\LocalizedRoutes\Tests\Stubs\Model;
12+
use CodeZero\LocalizedRoutes\Middleware\SetLocale;
13+
use CodeZero\LocalizedRoutes\Tests\Stubs\ModelBar;
14+
use CodeZero\LocalizedRoutes\Tests\Stubs\ModelFoo;
15+
use Illuminate\Database\Eloquent\ModelNotFoundException;
16+
use CodeZero\LocalizedRoutes\Tests\Stubs\ModelWithCustomRouteParameters;
1517

1618
class LocalizedUrlMacroTest extends TestCase
1719
{
@@ -49,6 +51,48 @@ public function it_generates_urls_with_default_localized_route_keys_for_the_curr
4951
], $response->original);
5052
}
5153

54+
/** @test */
55+
public function it_generates_urls_for_the_current_route_with_diferent_models_using_route_model_binding()
56+
{
57+
$this->withoutExceptionHandling();
58+
$this->setSupportedLocales(['en', 'nl']);
59+
60+
$foo = (new ModelFoo([
61+
'slug' => [
62+
'en' => 'en-slug-foo',
63+
'nl' => 'nl-slug-foo',
64+
],
65+
]))->setKeyName('slug');
66+
67+
$bar = (new ModelBar([
68+
'slug' => [
69+
'en' => 'en-slug-bar',
70+
'nl' => 'nl-slug-bar',
71+
],
72+
]))->setKeyName('slug');
73+
74+
App::instance(ModelFoo::class, $foo);
75+
App::instance(ModelBar::class, $bar);
76+
77+
Route::localized(function () {
78+
Route::get('route/{foo}/{bar}', function (ModelFoo $foo, ModelBar $bar) {
79+
return [
80+
'current' => Route::localizedUrl(),
81+
'en' => Route::localizedUrl('en'),
82+
'nl' => Route::localizedUrl('nl'),
83+
];
84+
})->middleware(['web']);
85+
});
86+
87+
$response = $this->call('GET', '/en/route/en-slug-foo/en-slug-bar');
88+
$response->assertOk();
89+
$this->assertEquals([
90+
'current' => url('/en/route/en-slug-foo/en-slug-bar'),
91+
'en' => url('/en/route/en-slug-foo/en-slug-bar'),
92+
'nl' => url('/nl/route/nl-slug-foo/nl-slug-bar'),
93+
], $response->original);
94+
}
95+
5296
/** @test */
5397
public function it_generates_urls_with_custom_localized_route_keys_for_the_current_route_using_route_model_binding()
5498
{
@@ -208,7 +252,6 @@ public function you_can_pass_it_a_closure_that_returns_the_parameters_without_ro
208252

209253
Route::localized(function () use ($model) {
210254
Route::get('route/{id}/{slug}', function ($id, $slug) use ($model) {
211-
212255
$closure = function ($locale) use ($model) {
213256
return [$model->id, $model->getSlug($locale)];
214257
};
@@ -830,7 +873,6 @@ public function it_handles_capitalized_parameter_names()
830873
'en' => url('/route/another-slug'),
831874
'nl' => url('/route/another-slug'),
832875
], $response->original);
833-
834876
}
835877

836878
/** @test */

tests/Unit/RouteModelBindingTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
namespace CodeZero\LocalizedRoutes\Tests\Unit;
44

5-
use CodeZero\LocalizedRoutes\Tests\Stubs\Model;
6-
use CodeZero\LocalizedRoutes\Tests\TestCase;
75
use Illuminate\Support\Facades\App;
86
use Illuminate\Support\Facades\Route;
7+
use CodeZero\LocalizedRoutes\Tests\TestCase;
8+
use CodeZero\LocalizedRoutes\Tests\Stubs\Model;
99

1010
class RouteModelBindingTest extends TestCase
1111
{

0 commit comments

Comments
 (0)