PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.5
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.5
1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk All 48 releases
← All changes | app/Http/Requests/AttrTermRequest.php +65 -30 1.3.19 → 1.6.5 View file →
@@ -1,55 +1,90 @@
1 1 <?php
2 2
3 3 namespace FluentCart\App\Http\Requests;
4 4
5 +use FluentCart\App\Models\AttributeGroup;
5 6 use FluentCart\Framework\Foundation\RequestGuard;
7 +use FluentCart\Framework\Support\Arr;
6 8
7 9 class AttrTermRequest extends RequestGuard
8 10 {
9 -
10 - /**
11 - * @return array
12 - */
13 11 public function rules()
14 12 {
15 - $termId = $this->get('term_id');
16 - $tbl = 'fct_atts_terms';
13 + // Term slugs are uniquely scoped per group at the DB layer (composite UNIQUE
14 + // index on (group_id, slug) in AttributeTermsMigrator), so two groups can
15 + // share a term slug ("red" in Color and "red" in Theme). The Resource layer
16 + // handles per-group dedup + auto-suffixing; let the DB enforce final uniqueness
17 + // instead of duplicating a global validator rule that would over-reject.
18 + $rules = [
19 + 'terms' => ['required', function ($_, $value) {
20 + if (\is_array($value) && \count($value) > 10) {
21 + return esc_html__('Cannot create more than 10 terms at once.', 'fluent-cart');
22 + }
23 + }],
24 + 'terms.*.title' => 'required|sanitizeText|maxLength:50',
25 + 'terms.*.settings' => 'nullable',
26 + ];
17 27
18 - /**
19 - * todo - consult with heera bhai how to proceed with this composit unique validation
20 - *
21 - */
28 + // Type-aware settings validation. The group's `settings.type` decides
29 + // whether each term row needs a color (hex string) or image (URL) —
30 + // an `image` group with no thumbnail would render an empty swatch in
31 + // the picker chips, and a `color` group with no hex breaks the dot.
32 + $groupType = $this->getGroupType();
33 + if ($groupType === 'color') {
34 + // The sanitize() map runs `sanitize_hex_color` on this field,
35 + // which returns an empty string for anything that isn't a valid
36 + // `#rgb` / `#rrggbb` — so `required` here doubles as the hex
37 + // validator without a separate regex rule.
38 + $rules['terms.*.settings.color'] = ['required'];
39 + } elseif ($groupType === 'image') {
40 + $rules['terms.*.settings.image'] = ['required', 'url'];
41 + }
42 +
43 + return $rules;
44 + }
45 +
46 + public function messages()
47 + {
22 48 return [
23 - 'title' => 'required|sanitizeText|maxLength:50|unique:' . $tbl . ',title,'.$termId.',id',
24 - 'slug' => 'required|sanitizeText|maxLength:50|unique:' . $tbl . ',slug,'.$termId.',id',
25 - 'description' => 'nullable|sanitizeTextArea',
26 - 'serial' => 'nullable|numeric'
49 + 'terms.required' => esc_html__('At least one term is required.', 'fluent-cart'),
50 + 'terms.*.title.required' => esc_html__('Each term must have a title.', 'fluent-cart'),
51 + 'terms.*.title.maxLength' => esc_html__('Each title must be 50 characters or fewer.', 'fluent-cart'),
52 + 'terms.*.settings.color.required' => esc_html__('A color is required for each term in a color group.', 'fluent-cart'),
53 + 'terms.*.settings.image.required' => esc_html__('An image is required for each term in an image group.', 'fluent-cart'),
54 + 'terms.*.settings.image.url' => esc_html__('Image must be a valid URL.', 'fluent-cart'),
27 55 ];
28 56 }
29 57
30 -
31 - /**
32 - * @return array
33 - */
34 - public function messages()
58 + public function sanitize()
35 59 {
36 60 return [
37 - 'title.required' => esc_html__('Title is required', 'fluent-cart'),
38 - 'slug.required' => esc_html__('Slug is required', 'fluent-cart'),
39 -
61 + 'terms.*.title' => 'sanitize_text_field',
62 + // sanitize_hex_color() returns null for anything that isn't a
63 + // valid `#rgb` / `#rrggbb` — the rules() `required` check then
64 + // surfaces the user-facing "color is required" error.
65 + 'terms.*.settings.color' => 'sanitize_hex_color',
66 + 'terms.*.settings.image' => 'esc_url_raw',
40 67 ];
41 68 }
42 69
43 -
44 70 /**
45 - * @return array
71 + * Look up the parent attribute group's type ('color' | 'image' | 'options')
72 + * so the rules() can require the matching settings field. The {group_id}
73 + * URL param is merged into the request inputs via WP_REST_Request::get_params(),
74 + * so $this->get() resolves it without touching the controller signature.
75 + *
76 + * @return string|null
46 77 */
47 - public function sanitize()
78 + protected function getGroupType()
48 79 {
49 - return [
50 - 'serial' => 'sanitize_text_field',
51 - 'description' => 'sanitize_text_field',
52 - 'slug' => 'sanitize_text_field'
53 - ];
80 + $groupId = (int) $this->get('group_id', 0);
81 + if ($groupId <= 0) {
82 + return null;
83 + }
84 + $group = AttributeGroup::query()->find($groupId);
85 + if (!$group) {
86 + return null;
87 + }
88 + return Arr::get($group->settings ?: [], 'type');
54 89 }
55 90 }