Test Failed
Push — develop ( a4d1ea...33b521 )
by Paul
10:24
created

CreateReview::reloadedSummary()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 8
rs 10
c 0
b 0
f 0
ccs 7
cts 7
cp 1
cc 3
nc 2
nop 0
crap 3
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Commands;
4
5
use GeminiLabs\SiteReviews\Arguments;
6
use GeminiLabs\SiteReviews\Database\ReviewManager;
7
use GeminiLabs\SiteReviews\Defaults\CreateReviewDefaults;
8
use GeminiLabs\SiteReviews\Defaults\CustomFieldsDefaults;
9
use GeminiLabs\SiteReviews\Helper;
10
use GeminiLabs\SiteReviews\Helpers\Arr;
11
use GeminiLabs\SiteReviews\Helpers\Str;
12
use GeminiLabs\SiteReviews\Helpers\Url;
13
use GeminiLabs\SiteReviews\Modules\Avatar;
14
use GeminiLabs\SiteReviews\Modules\Validator\CustomValidator;
15
use GeminiLabs\SiteReviews\Modules\Validator\DefaultValidator;
16
use GeminiLabs\SiteReviews\Modules\Validator\DuplicateValidator;
17
use GeminiLabs\SiteReviews\Modules\Validator\ValidateForm;
18
use GeminiLabs\SiteReviews\Request;
19
use GeminiLabs\SiteReviews\Review;
20
use GeminiLabs\SiteReviews\Shortcodes\SiteReviewsShortcode;
21
use GeminiLabs\SiteReviews\Shortcodes\SiteReviewsSummaryShortcode;
22
23
class CreateReview extends AbstractCommand
24
{
25
    public $assigned_posts;
26
    public $assigned_terms;
27
    public $assigned_users;
28
    public $author_id;
29
    public $avatar;
30
    public $content;
31
    public $custom;
32
    public $date;
33
    public $date_gmt;
34
    public $email;
35
    public $form_id;
36
    public $ip_address;
37
    public $is_approved;
38
    public $is_pinned;
39
    public $is_verified;
40
    public $name;
41
    public $post_id;
42
    public $rating;
43
    public $referer;
44
    public $request;
45
    public $response;
46
    public $response_by;
47
    public $terms;
48
    public $terms_exist;
49
    public $title;
50
    public $type;
51
    public $url;
52
53
    protected Review $review;
54
    protected Arguments $validation;
55
56 25
    public function __construct(Request $request)
57
    {
58 25
        $this->request = $this->normalize($request); // IP address is set here
59 25
        $this->setProperties(); // do this after setting the request
60 25
        $this->review = new Review($this->toArray(), $init = false);
61 25
        $this->validation = new Arguments();
62 25
        $this->custom = $this->custom();
63 25
        $this->type = $this->type();
64 25
        $this->avatar = $this->avatar(); // do this last
65
    }
66
67 8
    public function handle(): void
68
    {
69 8
        if ($this->validate()) {
70 7
            $this->create(); // public form submission
71
        }
72
    }
73
74
    public function isBlacklisted(): bool
75
    {
76
        return $this->validation->cast('blacklisted', 'bool') && 'local' === $this->type;
77
    }
78 4
79
    /**
80 4
     * This method is used to validate the request instead of the "validate" method
81 4
     * when creating a review with the "glsr_create_review" function.
82 4
     */
83 4
    public function isRequestValid(): bool
84 4
    {
85 4
        $request = clone $this->request;
86 4
        $excluded = array_keys(array_diff_key(
87 4
            Arr::consolidate(glsr()->settings('settings.forms.required.options')),
88 4
            $this->request->toArray(),
89 4
        ));
90 4
        $request->merge(compact('excluded'));
91 4
        $validators = glsr()->filterArray('validators', [ // order is intentional
92 4
            DefaultValidator::class,
93 4
            DuplicateValidator::class,
94
            CustomValidator::class,
95
        ]);
96
        $validator = glsr(ValidateForm::class)->validate($request, $validators);
97 4
        if ($validator->isValid()) {
98 4
            return true;
99
        }
100
        glsr_log()->warning($validator->result()->errors);
101
        return false;
102
    }
103
104
    public function referer(): string
105
    {
106
        if ($referer = $this->redirect($this->referer)) {
107
            return $referer;
108
        }
109
        glsr_log()->warning('The form referer ($_SERVER[REQUEST_URI]) was empty.')->debug($this->request);
110 8
        return Url::home();
111
    }
112 8
113 8
    public function reloadedReviews(): string
114
    {
115
        $args = $this->request->cast('_reviews_atts', 'array');
116
        if (!empty($args) && $this->review->is_approved) {
117
            $paginationArgs = $this->request->cast('_pagination_atts', 'array');
118
            glsr()->store(glsr()->paged_handle, $paginationArgs);
119
            return glsr(SiteReviewsShortcode::class)
120 8
                ->normalize($args, $args['from'] ?? 'shortcode')
121
                ->buildTemplate();
122
        }
123 8
        return '';
124
    }
125 8
126 8
    public function reloadedSummary(): string
127 8
    {
128 8
        $args = $this->request->cast('_summary_atts', 'array');
129 8
        if (!empty($args) && $this->review->is_approved) {
130 8
            return glsr(SiteReviewsSummaryShortcode::class)
131 8
                ->build($args, $args['from'] ?? 'shortcode');
132 8
        }
133
        return '';
134
    }
135 8
136
    public function response(): array
137 8
    {
138 7
        return [
139 7
            'errors' => $this->validation->array('errors'),
140
            'html' => (string) $this->review,
141 8
            'message' => $this->validation->cast('message', 'string'),
142
            'redirect' => $this->redirect(),
143
            'review' => $this->review->toArray(['email', 'ip_address']),
144 25
            'reviews' => $this->reloadedReviews(),
145
            'summary' => $this->reloadedSummary(),
146 25
            'success' => $this->successful(),
147 25
        ];
148 25
    }
149
150
    public function successful(): bool
151 8
    {
152
        return false === $this->validation->failed;
153 8
    }
154 8
155 8
    public function toArray(): array
156 8
    {
157 8
        $values = get_object_vars($this);
158
        $values = glsr()->filterArray('create/review-values', $values, $this);
159
        return glsr(CreateReviewDefaults::class)->merge($values); // don't restrict values
160 25
    }
161
162 25
    public function validate(): bool
163 25
    {
164
        $validator = glsr(ValidateForm::class)->validate($this->request);
165
        $this->validation = $validator->result();
166
        return $validator->isValid();
167
    }
168 7
169
    protected function avatar(): string
170 7
    {
171 7
        if (!defined('WP_IMPORTING') && empty($this->avatar)) {
172 7
            return glsr(Avatar::class)->generate($this->review);
173 1
        }
174 7
        return $this->avatar;
175 7
    }
176
177
    protected function create(): void
178
    {
179
        $message = __('Your review could not be submitted and the error has been logged. Please notify the site administrator.', 'site-reviews');
180
        if ($review = glsr(ReviewManager::class)->create($this)) {
181 25
            $this->review = $review; // overwrite the dummy review with the submitted review
182
            $message = $review->is_approved
183 25
                ? __('Your review has been submitted!', 'site-reviews')
184
                : __('Your review has been submitted and is pending approval.', 'site-reviews');
185
        }
186 25
        $this->validation->set('message', $message);
187
    }
188 25
189 25
    protected function custom(): array
190 24
    {
191
        $fields = [];
192 25
        foreach ($this->request->toArray() as $key => $value) {
193
            $key = Str::removePrefix($key, 'custom_');
194 22
            $fields[$key] = $value;
195 22
        }
196 22
        return glsr(CustomFieldsDefaults::class)->filter($fields);
197 22
    }
198 22
199
    protected function normalize(Request $request): Request
200 25
    {
201 25
        $isFormSubmission = !defined('WP_IMPORTING') && !glsr()->retrieve('glsr_create_review', false);
202
        if ($isFormSubmission || empty($request->ip_address)) {
203
            $request->set('ip_address', Helper::getIpAddress()); // required for Akismet and Blacklist validation
204 8
        }
205
        if ($isFormSubmission) {
206 8
            // is_approved is set when the review is created
207 8
            $request->set('author_id', get_current_user_id());
208 8
            $request->set('is_pinned', false);
209 8
            $request->set('is_verified', false);
210
            $request->set('response', '');
211 8
            $request->set('response_by', 0);
212
        }
213
        glsr()->action('review/request', $request);
214 25
        return $request;
215
    }
216 25
217 25
    protected function redirect(string $fallback = ''): string
218 25
    {
219 25
        $redirect = trim(strval(get_post_meta($this->post_id, 'redirect_to', true)));
220
        $redirect = glsr()->filterString('review/redirect', $redirect, $this, $this->review);
221
        if (empty($redirect)) {
222 25
            $redirect = $fallback;
223
        }
224
        return sanitize_text_field($redirect);
225
    }
226
227 25
    protected function setProperties(): void
228
    {
229 25
        $properties = (new \ReflectionClass($this))->getProperties(\ReflectionProperty::IS_PUBLIC);
230 25
        $values = glsr(CreateReviewDefaults::class)->restrict($this->request->toArray());
231
        foreach ($properties as $property) {
232
            $key = $property->getName();
233
            if (array_key_exists($key, $values)) {
234
                $property->setValue($this, $values[$key]);
235
            }
236
        }
237
        if (!empty($this->date) && empty($this->date_gmt)) {
238
            $this->date_gmt = get_gmt_from_date($this->date); // set the GMT date
239
        }
240
    }
241
242
    protected function type(): string
243
    {
244
        $reviewTypes = glsr()->retrieveAs('array', 'review_types');
245
        return array_key_exists($this->type, $reviewTypes) ? $this->type : 'local';
246
    }
247
}
248