Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
86.67% covered (warning)
86.67%
26 / 30
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
ProductSpecController
86.67% covered (warning)
86.67%
26 / 30
50.00% covered (danger)
50.00%
1 / 2
5.06
0.00% covered (danger)
0.00%
0 / 1
 edit
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 update
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
1 / 1
4
1<?php
2
3namespace App\Http\Controllers\admin;
4
5use App\Http\Controllers\Controller;
6use App\Models\admin\Product;
7use App\Models\ProductSpec;
8use App\Models\SpecGroup;
9use Illuminate\Http\RedirectResponse;
10use Illuminate\Http\Request;
11use Illuminate\Support\Facades\DB;
12use Illuminate\View\View;
13
14/**
15 * Technical specifications for a product — grouped label/value rows shown on
16 * the product page and (when flagged) usable as shop filters.
17 */
18class ProductSpecController extends Controller
19{
20    public function edit(Product $product): View
21    {
22        return view('admin.products.specs', [
23            'product' => $product->load('specs.group'),
24            'groups' => SpecGroup::orderBy('sort_order')->orderBy('name')->pluck('name'),
25        ]);
26    }
27
28    public function update(Request $request, Product $product): RedirectResponse
29    {
30        $rows = collect($request->input('specs', []))
31            ->filter(fn ($r) => filled($r['label'] ?? null) && filled($r['value'] ?? null))
32            ->values();
33
34        DB::transaction(function () use ($product, $rows) {
35            $groupIds = [];
36            $resolveGroup = function (?string $name) use (&$groupIds) {
37                $name = trim((string) $name);
38                if ($name === '') {
39                    return null;
40                }
41
42                return $groupIds[$name] ??= SpecGroup::firstOrCreate(['name' => $name])->id;
43            };
44
45            $product->specs()->delete();
46
47            foreach ($rows as $i => $row) {
48                ProductSpec::create([
49                    'product_id' => $product->id,
50                    'spec_group_id' => $resolveGroup($row['group'] ?? null),
51                    'label' => trim($row['label']),
52                    'value' => trim($row['value']),
53                    'is_filterable' => (bool) ($row['is_filterable'] ?? false),
54                    'sort_order' => $i,
55                ]);
56            }
57
58            // drop groups nobody uses any more
59            SpecGroup::doesntHave('specs')->delete();
60        });
61
62        return redirect()
63            ->route('admin.product.specs.edit', $product)
64            ->with('success', 'Specifications saved.');
65    }
66}