PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / trunk
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler vtrunk
1.7.0 1.6.6 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 All 50 releases
fluent-cart / app / Http / Requests / ReviewCreateRequest.php

ReviewCreateRequest.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler trunk, at app/Http/Requests/ReviewCreateRequest.php

115 lines 5.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Http\Requests;
4
5 use FluentCart\App\Helpers\Status;
6 use FluentCart\App\Services\ProductReviewService;
7 use FluentCart\Framework\Foundation\RequestGuard;
8
9 /**
10 * An admin-authored review. The shared ReviewRequest serves ten list and
11 * moderation actions and can require nothing; creating a review has
12 * required fields, so they are declared here, the way product create has
13 * its own request class. A failure answers 422 with {field: {rule: message}},
14 * which the Add Review form prints under each field.
15 */
16 class ReviewCreateRequest extends RequestGuard
17 {
18 /**
19 * The required text fields are checked as they will be stored. The rules
20 * run on the raw request, and sanitize_textarea_field() can strip a
21 * markup-only body to nothing afterwards — "required" would pass and an
22 * empty review would be saved. Cleaning them first closes that gap.
23 *
24 * @return array
25 */
26 public function beforeValidation()
27 {
28 $data = $this->all();
29
30 // Text fields only: an array or object here is not text, and casting
31 // it would yield the literal "Array", which "required" would accept.
32 $clean = static function ($value, callable $sanitizer) {
33 return is_scalar($value) ? trim($sanitizer((string) $value)) : '';
34 };
35
36 if (array_key_exists('content', $data)) {
37 $data['content'] = $clean($data['content'], 'sanitize_textarea_field');
38 }
39 if (array_key_exists('reviewer_name', $data)) {
40 $data['reviewer_name'] = $clean($data['reviewer_name'], 'sanitize_text_field');
41 }
42 if (array_key_exists('title', $data)) {
43 $data['title'] = $clean($data['title'], 'sanitize_text_field');
44 }
45
46 return $data;
47 }
48
49 public function rules(): array
50 {
51 // Optional, unlike the guest storefront path: a moderator transcribing
52 // a review from a phone call may have no address to enter. When one is
53 // given it still has to be real, because the customer link and the
54 // avatar are resolved from it.
55 $rules = [
56 'post_id' => 'required|numeric',
57 // The variation being reviewed, when the product has variations
58 // worth telling apart. The controller checks it belongs to the
59 // product — a rule cannot see post_id's value.
60 'item_id' => 'nullable|numeric',
61 'content' => 'required|maxLength:5000',
62 'reviewer_name' => 'required|sanitizeText|maxLength:100',
63 'reviewer_email' => 'nullable|sanitizeText|email|maxLength:192',
64 'title' => 'nullable|sanitizeText|maxLength:192',
65 'rating' => 'nullable|numeric|min:0|max:5',
66 'status' => 'nullable|sanitizeText|in:' . implode(',', Status::getReviewStatuses()),
67 'is_verified' => 'nullable|numeric|min:0|max:1',
68 ];
69
70 // A store that collects ratings and requires them refuses a review
71 // without one; with ratings optional or off, 0 means "none".
72 if (ProductReviewService::isStarRatingRequired()) {
73 $rules['rating'] = 'required|numeric|min:1|max:5';
74 }
75
76 return $rules;
77 }
78
79 public function messages(): array
80 {
81 return [
82 'post_id.required' => esc_html__('Please select a product for this review.', 'fluent-cart'),
83 'post_id.numeric' => esc_html__('Please select a product for this review.', 'fluent-cart'),
84 'item_id.numeric' => esc_html__('Please select a valid variation for this review.', 'fluent-cart'),
85 'content.required' => esc_html__('Review content is required.', 'fluent-cart'),
86 'content.maxLength' => esc_html__('Review content must not exceed 5000 characters.', 'fluent-cart'),
87 'reviewer_name.required' => esc_html__('Reviewer name is required.', 'fluent-cart'),
88 'reviewer_name.maxLength' => esc_html__('Reviewer name must not exceed 100 characters.', 'fluent-cart'),
89 'reviewer_email.email' => esc_html__('A valid email address is required', 'fluent-cart'),
90 'reviewer_email.maxLength' => esc_html__('Email address must not exceed 192 characters.', 'fluent-cart'),
91 'title.maxLength' => esc_html__('Review title must not exceed 192 characters.', 'fluent-cart'),
92 'rating.required' => esc_html__('Star rating is required', 'fluent-cart'),
93 'rating.numeric' => esc_html__('Rating must be a number.', 'fluent-cart'),
94 'rating.min' => esc_html__('Star rating is required', 'fluent-cart'),
95 'rating.max' => esc_html__('Rating must not exceed 5.', 'fluent-cart'),
96 'status.in' => esc_html__('Invalid status', 'fluent-cart'),
97 ];
98 }
99
100 public function sanitize(): array
101 {
102 return [
103 'post_id' => 'intval',
104 'item_id' => 'intval',
105 'content' => 'sanitize_textarea_field',
106 'reviewer_name' => 'sanitize_text_field',
107 'reviewer_email' => 'sanitize_email',
108 'title' => 'sanitize_text_field',
109 'rating' => 'intval',
110 'status' => 'sanitize_text_field',
111 'is_verified' => 'intval',
112 ];
113 }
114 }
115