Skip to content

Commit 2ef6b54

Browse files
committed
Resourceful routing
1 parent ebb4d63 commit 2ef6b54

File tree

2 files changed

+92
-0
lines changed

2 files changed

+92
-0
lines changed

src/Elements/Form.php

+31
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
use Galahad\Aire\Aire;
77
use Galahad\Aire\Elements\Concerns\CreatesElements;
88
use Galahad\Aire\Elements\Concerns\CreatesInputTypes;
9+
use Illuminate\Database\Eloquent\Model;
910
use Illuminate\Foundation\Http\FormRequest;
1011
use Illuminate\Routing\Router;
1112
use Illuminate\Routing\UrlGenerator;
1213
use Illuminate\Session\Store;
1314
use Illuminate\Support\HtmlString;
15+
use Illuminate\Support\Str;
1416
use Illuminate\Support\ViewErrorBag;
1517

1618
class Form extends \Galahad\Aire\DTD\Form
@@ -139,6 +141,35 @@ public function bind($bound_data) : self
139141
return $this;
140142
}
141143

144+
/**
145+
* Bind data with implicit resource controller routing
146+
*
147+
* Form::resourceful(new User()) -> POST route('users.store')
148+
* Form::resourceful($existing_user) -> PUT route('users.update')
149+
*
150+
* @param \Illuminate\Database\Eloquent\Model $model
151+
* @param string $resource_name
152+
* @return \Galahad\Aire\Elements\Form
153+
*/
154+
public function resourceful(Model $model, $resource_name = null) : self
155+
{
156+
$this->bind($model);
157+
158+
if (null === $resource_name) {
159+
$resource_name = Str::kebab(Str::plural($model->getTable()));
160+
}
161+
162+
if ($model->exists) {
163+
$this->action($this->url->route("{$resource_name}.update", $model));
164+
$this->put();
165+
} else {
166+
$this->action($this->url->route("{$resource_name}.store"));
167+
$this->post();
168+
}
169+
170+
return $this;
171+
}
172+
142173
/**
143174
* Determine whether the form has any bound data
144175
*
+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<?php
2+
3+
/** @noinspection ReturnTypeCanBeDeclaredInspection */
4+
5+
namespace Galahad\Aire\Tests\Feature;
6+
7+
use Galahad\Aire\Tests\TestCase;
8+
use Illuminate\Database\Eloquent\Model;
9+
use Illuminate\Support\Facades\Route;
10+
use Illuminate\Support\Facades\URL;
11+
12+
class ResourcefulBindingTest extends TestCase
13+
{
14+
protected function setUp()
15+
{
16+
parent::setUp();
17+
18+
Route::post('/users', function() {})->name('users.store');
19+
Route::put('/users/{user}', function() {})->name('users.update');
20+
}
21+
22+
public function test_action_and_method_are_inferred_for_unsaved_models()
23+
{
24+
$model = new XResourcefulModel(['id' => 1]);
25+
26+
$html = $this->aire()->form()->resourceful($model)->render();
27+
28+
$this->assertSelectorAttribute($html, 'form', 'action', URL::to('/users'));
29+
$this->assertSelectorAttribute($html, 'form', 'method', 'POST');
30+
$this->assertSelectorDoesNotExist($html, 'input[name="_method"]');
31+
}
32+
33+
public function test_action_and_method_are_inferred_for_saved_models()
34+
{
35+
$model = new XResourcefulModel(['id' => 1]);
36+
$model->exists = true;
37+
38+
$html = $this->aire()->form()->resourceful($model)->render();
39+
40+
$this->assertSelectorAttribute($html, 'form', 'action', URL::to('/users/1'));
41+
$this->assertSelectorAttribute($html, 'input[name="_method"]', 'value', 'PUT');
42+
}
43+
44+
public function test_provided_name_overrides_inferred_name() : void
45+
{
46+
Route::post('/foo/bar', function() {})->name('foo.bar.store');
47+
48+
$model = new XResourcefulModel(['id' => 1]);
49+
50+
$html = $this->aire()->form()->resourceful($model, 'foo.bar')->render();
51+
52+
$this->assertSelectorAttribute($html, 'form', 'action', URL::to('/foo/bar'));
53+
}
54+
}
55+
56+
class XResourcefulModel extends Model
57+
{
58+
protected $guarded = [];
59+
60+
protected $table = 'users';
61+
}

0 commit comments

Comments
 (0)