Test Failed
Push — develop ( 325b33...c75138 )
by Paul
09:01
created

CreateReview::isBlacklisted()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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