Skip to content

Commit bf4e32d

Browse files
committed
Part 16 - Customizing Views & Controllers in Voyager
1 parent 6aeef27 commit bf4e32d

File tree

4 files changed

+815
-0
lines changed

4 files changed

+815
-0
lines changed

app/CategoryProduct.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@
77
class CategoryProduct extends Model
88
{
99
protected $table = 'category_product';
10+
11+
protected $fillable = ['product_id', 'category_id'];
1012
}
Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
<?php
2+
3+
namespace App\Http\Controllers\Voyager;
4+
5+
use App\Product;
6+
use App\Category;
7+
use App\CategoryProduct;
8+
use Illuminate\Http\Request;
9+
use TCG\Voyager\Facades\Voyager;
10+
use Illuminate\Support\Facades\DB;
11+
use TCG\Voyager\Events\BreadDataAdded;
12+
use Illuminate\Database\Eloquent\Model;
13+
use TCG\Voyager\Events\BreadDataDeleted;
14+
use TCG\Voyager\Events\BreadDataUpdated;
15+
use TCG\Voyager\Events\BreadImagesDeleted;
16+
use TCG\Voyager\Database\Schema\SchemaManager;
17+
use TCG\Voyager\Http\Controllers\VoyagerBreadController;
18+
use TCG\Voyager\Http\Controllers\Traits\BreadRelationshipParser;
19+
20+
class ProductsController extends VoyagerBreadController
21+
{
22+
use BreadRelationshipParser;
23+
//***************************************
24+
// ____
25+
// | _ \
26+
// | |_) |
27+
// | _ <
28+
// | |_) |
29+
// |____/
30+
//
31+
// Browse our Data Type (B)READ
32+
//
33+
//****************************************
34+
35+
public function index(Request $request)
36+
{
37+
// GET THE SLUG, ex. 'posts', 'pages', etc.
38+
$slug = $this->getSlug($request);
39+
40+
// GET THE DataType based on the slug
41+
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first();
42+
43+
// Check permission
44+
$this->authorize('browse', app($dataType->model_name));
45+
46+
$getter = $dataType->server_side ? 'paginate' : 'get';
47+
48+
$search = (object) ['value' => $request->get('s'), 'key' => $request->get('key'), 'filter' => $request->get('filter')];
49+
$searchable = $dataType->server_side ? array_keys(SchemaManager::describeTable(app($dataType->model_name)->getTable())->toArray()) : '';
50+
$orderBy = $request->get('order_by');
51+
$sortOrder = $request->get('sort_order', null);
52+
53+
// Next Get or Paginate the actual content from the MODEL that corresponds to the slug DataType
54+
if (strlen($dataType->model_name) != 0) {
55+
$model = app($dataType->model_name);
56+
$query = $model::select('*');
57+
58+
$relationships = $this->getRelationships($dataType);
59+
60+
// If a column has a relationship associated with it, we do not want to show that field
61+
$this->removeRelationshipField($dataType, 'browse');
62+
63+
if ($search->value && $search->key && $search->filter) {
64+
$search_filter = ($search->filter == 'equals') ? '=' : 'LIKE';
65+
$search_value = ($search->filter == 'equals') ? $search->value : '%'.$search->value.'%';
66+
$query->where($search->key, $search_filter, $search_value);
67+
}
68+
69+
if ($orderBy && in_array($orderBy, $dataType->fields())) {
70+
$querySortOrder = (!empty($sortOrder)) ? $sortOrder : 'DESC';
71+
$dataTypeContent = call_user_func([
72+
$query->with($relationships)->orderBy($orderBy, $querySortOrder),
73+
$getter,
74+
]);
75+
} elseif ($model->timestamps) {
76+
$dataTypeContent = call_user_func([$query->latest($model::CREATED_AT), $getter]);
77+
} else {
78+
$dataTypeContent = call_user_func([$query->with($relationships)->orderBy($model->getKeyName(), 'DESC'), $getter]);
79+
}
80+
81+
// Replace relationships' keys for labels and create READ links if a slug is provided.
82+
$dataTypeContent = $this->resolveRelations($dataTypeContent, $dataType);
83+
} else {
84+
// If Model doesn't exist, get data from table name
85+
$dataTypeContent = call_user_func([DB::table($dataType->name), $getter]);
86+
$model = false;
87+
}
88+
89+
// Check if BREAD is Translatable
90+
if (($isModelTranslatable = is_bread_translatable($model))) {
91+
$dataTypeContent->load('translations');
92+
}
93+
94+
// Check if server side pagination is enabled
95+
$isServerSide = isset($dataType->server_side) && $dataType->server_side;
96+
97+
$view = 'voyager::bread.browse';
98+
99+
if (view()->exists("voyager::$slug.browse")) {
100+
$view = "voyager::$slug.browse";
101+
}
102+
103+
return Voyager::view($view, compact(
104+
'dataType',
105+
'dataTypeContent',
106+
'isModelTranslatable',
107+
'search',
108+
'orderBy',
109+
'sortOrder',
110+
'searchable',
111+
'isServerSide'
112+
));
113+
}
114+
115+
//***************************************
116+
// ______
117+
// | ____|
118+
// | |__
119+
// | __|
120+
// | |____
121+
// |______|
122+
//
123+
// Edit an item of our Data Type BR(E)AD
124+
//
125+
//****************************************
126+
127+
public function edit(Request $request, $id)
128+
{
129+
$slug = $this->getSlug($request);
130+
131+
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first();
132+
133+
// Compatibility with Model binding.
134+
$id = $id instanceof Model ? $id->{$id->getKeyName()} : $id;
135+
136+
$relationships = $this->getRelationships($dataType);
137+
138+
$dataTypeContent = (strlen($dataType->model_name) != 0)
139+
? app($dataType->model_name)->with($relationships)->findOrFail($id)
140+
: DB::table($dataType->name)->where('id', $id)->first(); // If Model doest exist, get data from table name
141+
142+
foreach ($dataType->editRows as $key => $row) {
143+
$details = json_decode($row->details);
144+
$dataType->editRows[$key]['col_width'] = isset($details->width) ? $details->width : 100;
145+
}
146+
147+
// If a column has a relationship associated with it, we do not want to show that field
148+
$this->removeRelationshipField($dataType, 'edit');
149+
150+
// Check permission
151+
$this->authorize('edit', $dataTypeContent);
152+
153+
// Check if BREAD is Translatable
154+
$isModelTranslatable = is_bread_translatable($dataTypeContent);
155+
156+
$view = 'voyager::bread.edit-add';
157+
158+
if (view()->exists("voyager::$slug.edit-add")) {
159+
$view = "voyager::$slug.edit-add";
160+
}
161+
162+
$allCategories = Category::all();
163+
164+
$product = Product::find($id);
165+
$categoriesForProduct = $product->categories()->get();
166+
167+
return Voyager::view($view, compact('dataType', 'dataTypeContent', 'isModelTranslatable', 'allCategories', 'categoriesForProduct'));
168+
}
169+
170+
// POST BR(E)AD
171+
public function update(Request $request, $id)
172+
{
173+
$slug = $this->getSlug($request);
174+
175+
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first();
176+
177+
// Compatibility with Model binding.
178+
$id = $id instanceof Model ? $id->{$id->getKeyName()} : $id;
179+
180+
$data = call_user_func([$dataType->model_name, 'findOrFail'], $id);
181+
182+
// Check permission
183+
$this->authorize('edit', $data);
184+
185+
// Validate fields with ajax
186+
$val = $this->validateBread($request->all(), $dataType->editRows);
187+
188+
if ($val->fails()) {
189+
return response()->json(['errors' => $val->messages()]);
190+
}
191+
192+
if (!$request->ajax()) {
193+
$requestNew = $request;
194+
$requestNew['price'] = $request->price * 100;
195+
196+
$this->insertUpdateData($requestNew, $slug, $dataType->editRows, $data);
197+
198+
event(new BreadDataUpdated($dataType, $data));
199+
200+
CategoryProduct::where('product_id', $id)->delete();
201+
202+
// Re-insert if there's at least one category checked
203+
$this->updateProductCategories($request, $id);
204+
205+
return redirect()
206+
->route("voyager.{$dataType->slug}.index")
207+
->with([
208+
'message' => __('voyager.generic.successfully_updated')." {$dataType->display_name_singular}",
209+
'alert-type' => 'success',
210+
]);
211+
}
212+
}
213+
214+
//***************************************
215+
//
216+
// /\
217+
// / \
218+
// / /\ \
219+
// / ____ \
220+
// /_/ \_\
221+
//
222+
//
223+
// Add a new item of our Data Type BRE(A)D
224+
//
225+
//****************************************
226+
227+
public function create(Request $request)
228+
{
229+
$slug = $this->getSlug($request);
230+
231+
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first();
232+
233+
// Check permission
234+
$this->authorize('add', app($dataType->model_name));
235+
236+
$dataTypeContent = (strlen($dataType->model_name) != 0)
237+
? new $dataType->model_name()
238+
: false;
239+
240+
foreach ($dataType->addRows as $key => $row) {
241+
$details = json_decode($row->details);
242+
$dataType->addRows[$key]['col_width'] = isset($details->width) ? $details->width : 100;
243+
}
244+
245+
// If a column has a relationship associated with it, we do not want to show that field
246+
$this->removeRelationshipField($dataType, 'add');
247+
248+
// Check if BREAD is Translatable
249+
$isModelTranslatable = is_bread_translatable($dataTypeContent);
250+
251+
$view = 'voyager::bread.edit-add';
252+
253+
if (view()->exists("voyager::$slug.edit-add")) {
254+
$view = "voyager::$slug.edit-add";
255+
}
256+
257+
$allCategories = Category::all();
258+
$categoriesForProduct = collect([]);
259+
260+
return Voyager::view($view, compact('dataType', 'dataTypeContent', 'isModelTranslatable', 'allCategories', 'categoriesForProduct'));
261+
}
262+
263+
/**
264+
* POST BRE(A)D - Store data.
265+
*
266+
* @param \Illuminate\Http\Request $request
267+
*
268+
* @return \Illuminate\Http\RedirectResponse
269+
*/
270+
public function store(Request $request)
271+
{
272+
$slug = $this->getSlug($request);
273+
274+
$dataType = Voyager::model('DataType')->where('slug', '=', $slug)->first();
275+
276+
// Check permission
277+
$this->authorize('add', app($dataType->model_name));
278+
279+
// Validate fields with ajax
280+
$val = $this->validateBread($request->all(), $dataType->addRows);
281+
282+
if ($val->fails()) {
283+
return response()->json(['errors' => $val->messages()]);
284+
}
285+
286+
if (!$request->ajax()) {
287+
$requestNew = $request;
288+
$requestNew['price'] = $request->price * 100;
289+
290+
$data = $this->insertUpdateData($requestNew, $slug, $dataType->addRows, new $dataType->model_name());
291+
292+
event(new BreadDataAdded($dataType, $data));
293+
294+
$this->updateProductCategories($request, $data->id);
295+
296+
return redirect()
297+
->route("voyager.{$dataType->slug}.index")
298+
->with([
299+
'message' => __('voyager.generic.successfully_added_new')." {$dataType->display_name_singular}",
300+
'alert-type' => 'success',
301+
]);
302+
}
303+
}
304+
305+
protected function updateProductCategories(Request $request, $id)
306+
{
307+
if ($request->category) {
308+
foreach ($request->category as $category) {
309+
CategoryProduct::create([
310+
'product_id' => $id,
311+
'category_id' => $category,
312+
]);
313+
}
314+
}
315+
}
316+
}

0 commit comments

Comments
 (0)