Completed
Push — master ( f283ed...875b97 )
by Neomerx
05:05
created

showAdvancedUsageWithCustomValidator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 64
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 64
rs 9.3956
c 0
b 0
f 0
cc 1
eloc 27
nc 1
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php namespace Sample;
2
3
/**
4
 * Copyright 2015-2017 [email protected]
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use DateTime;
20
use DateTimeInterface;
21
use Limoncello\Validation\ArrayValidator as vv;
22
use Limoncello\Validation\Contracts\Captures\CaptureAggregatorInterface;
23
use Limoncello\Validation\Contracts\Errors\ErrorAggregatorInterface;
24
use Limoncello\Validation\Contracts\Errors\ErrorInterface;
25
use Limoncello\Validation\SingleValidator as v;
26
use MessageFormatter;
27
use Sample\Validation\CustomErrorMessages;
28
use Sample\Validation\CustomRules as r;
29
30
/**
31
 * @package Sample
32
 */
33
class Application
34
{
35
    /**
36
     * @var bool
37
     */
38
    private $isOutputToConsole;
39
40
    /**
41
     * @param bool $isOutputToConsole
42
     */
43
    public function __construct(bool $isOutputToConsole = true)
44
    {
45
        $this->isOutputToConsole = $isOutputToConsole;
46
    }
47
48
    /**
49
     * @return void
50
     */
51
    public function run(): void
52
    {
53
        $this->showSingleValueValidation();
54
55
        $this->showArrayValuesValidation();
56
    }
57
58
    /**
59
     * Shows single value validation with built-in rules.
60
     */
61
    private function showSingleValueValidation(): void
62
    {
63
        $this->console('Basic usage sample.' . PHP_EOL);
64
        $this->console('===================' . PHP_EOL);
65
66
        // Let's build a rule that validates an input to be either `null` or a string from 5 to 10 characters.
67
        $validator = v::validator(
68
            r::nullable(r::isString(r::stringLengthBetween(5, 10)))
69
        );
70
71
        // let's try validation with valid input
72
        $input = null;
73 View Code Duplication
        if ($validator->validate($input) === true) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
74
            $this->console("Validation OK for `null`." . PHP_EOL);
75
        } else {
76
            assert(false, 'We should not be here.');
77
        }
78
        // another one
79
        $input = 'Hello';
80 View Code Duplication
        if ($validator->validate($input) === true) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
81
            $this->console("Validation OK for `$input`." . PHP_EOL);
82
        } else {
83
            assert(false, 'We should not be here.');
84
        }
85
        // this one should not pass the validation
86
        $input = 'This string is too long.';
87
        if ($validator->validate($input) === false) {
88
            $this->console("Input `$input` has not passed validation." . PHP_EOL);
89
            $this->printErrors($validator->getErrors());
90
        } else {
91
            assert(false, 'We should not be here.');
92
        }
93
94
        // next example demonstrates
95
        // - parsing strings as dates
96
        // - validation for dates
97
        // - data capture so you don't need to parse the input second time after validation
98
        $fromDate  = new DateTime('2001-02-03');
99
        $toDate    = new DateTime('2001-04-05');
100
        $validator = v::validator(
101
            r::isString(r::stringToDateTime(DATE_ATOM, r::between($fromDate, $toDate)))
102
                ->setName('my_date')->enableCapture()
103
        );
104
        $input     = '2001-03-04T05:06:07+08:00';
105
        if ($validator->validate($input) === true) {
106
            $this->console("Validation OK for `$input`." . PHP_EOL);
107
            $myDate = $validator->getCaptures()->get()['my_date'];
108
            // note that captured date is already DateTime
109
            assert($myDate instanceof DateTimeInterface);
110
        } else {
111
            assert(false, 'We should not be here.');
112
        }
113
114
        $this->console(PHP_EOL . PHP_EOL . PHP_EOL);
115
116
        // The output would be
117
        // -------------------------------------------------------------------------------------------------------
118
        // Basic usage sample.
119
        // ===================
120
        // Validation OK for `null`.
121
        // Validation OK for `Hello`.
122
        // Input `This string is too long to pass validation.` has not passed validation.
123
        // Validation failed for `This string is too long.` with: The value should be between 5 and 10 characters.
124
        // Validation OK for `2001-03-04T05:06:07+08:00`.
125
        // -------------------------------------------------------------------------------------------------------
126
    }
127
128
    /**
129
     * Shows validation for array values with custom rules.
130
     */
131
    private function showArrayValuesValidation(): void
132
    {
133
        $this->console('Advanced usage sample.' . PHP_EOL);
134
        $this->console('===================' . PHP_EOL);
135
136
        // Validation rules for input are
137
        // - `email` must be a string and a valid email value (as FILTER_VALIDATE_EMAIL describes)
138
        // - `first_name` required in input, must be a string with length from 1 to 255 characters
139
        // - `last_name` could be either `null` or if given it must be a string with length from 1 to 255 characters
140
        // - `payment_plan` must be a valid index for data in database (we will emulate request to database)
141
        $validator = vv::validator([
142
            'email'        => r::isEmail(),
143
            'first_name'   => r::isRequiredString(255),
144
            'last_name'    => r::isNullOrNonEmptyString(255),
145
            'payment_plan' => r::isExistingPaymentPlan(),
146
        ]);
147
148
        // Check with invalid data
149
        $invalidInput = [
150
            'email'        => 'john.dow',
151
            //'first_name' => 'John',
152
            'last_name'    => '',
153
            'payment_plan' => '123',
154
        ];
155
        $this->console('Invalid data (errors)' . PHP_EOL);
156
        $validator->validate($invalidInput);
157
        $this->printErrors($validator->getErrors());
158
        $this->console('Invalid data (captures)' . PHP_EOL);
159
        $this->printCaptures($validator->getCaptures());
160
161
        // Check with valid data
162
        $validInput = [
163
            'email'        => '[email protected]',
164
            'first_name'   => 'John',
165
            'last_name'    => null,
166
            'payment_plan' => '2',
167
        ];
168
        $this->console(PHP_EOL . 'Valid data (errors)' . PHP_EOL);
169
        $validator->validate($validInput);
170
        $this->printErrors($validator->getErrors());
171
        $this->console('Valid data (captures)' . PHP_EOL);
172
        $this->printCaptures($validator->getCaptures());
173
174
        // The output would be
175
        // -------------------------------------------------------------------------------------------------------
176
        // Advanced usage sample.
177
        // ===================
178
        // Invalid data (errors)
179
        // Param `email` failed for `john.dow` with: The value should be a valid email address.
180
        // Param `last_name` failed for `` with: The value should be between 1 and 255 characters.
181
        // Param `payment_plan` failed for `123` with: The value should be a valid payment plan.
182
        // Param `first_name` failed for `` with: The value is required.
183
        // Invalid data (captures)
184
        // No captures
185
        //
186
        // Valid data (errors)
187
        // No errors
188
        // Valid data (captures)
189
        // `email` = `[email protected]` (string)
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
190
        // `first_name` = `John` (string)
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
191
        // `last_name` = `` (NULL)
0 ignored issues
show
Unused Code Comprehensibility introduced by
54% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
192
        // `payment_plan` = `2` (integer)
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
193
        // -------------------------------------------------------------------------------------------------------
194
    }
195
196
    /**
197
     * @param ErrorAggregatorInterface $errors
198
     *
199
     * @return void
200
     */
201
    private function printErrors(ErrorAggregatorInterface $errors): void
202
    {
203
        $hasErrors = false;
204
205
        foreach ($errors->get() as $error) {
206
            $hasErrors = true;
207
            $this->printError($error);
208
        }
209
210
        if ($hasErrors === false) {
211
            $this->console('No errors' . PHP_EOL);
212
        }
213
    }
214
215
    /**
216
     * @param ErrorInterface $error
217
     *
218
     * @return void
219
     */
220
    private function printError(ErrorInterface $error): void
221
    {
222
        $paramName  = $error->getParameterName();
223
        $entry      = empty($paramName) ? 'Validation' : "Param `$paramName`";
224
        $paramValue = $error->getParameterValue();
225
        $errorMsg   = CustomErrorMessages::MESSAGES[$error->getMessageCode()];
226
        $context    = $error->getMessageContext();
227
        $errorMsg   = MessageFormatter::formatMessage('en', $errorMsg, $context !== null ? $context : []);
228
229
        $this->console("$entry failed for `$paramValue` with: $errorMsg" . PHP_EOL);
230
    }
231
232
    /**
233
     * @param CaptureAggregatorInterface $captures
234
     *
235
     * @return void
236
     */
237
    private function printCaptures(CaptureAggregatorInterface $captures): void
238
    {
239
        $hasCaptures = false;
240
241
        foreach ($captures->get() as $name => $value) {
242
            $hasCaptures = true;
243
            $type        = gettype($value);
244
            $this->console("`$name` = `$value` ($type)" . PHP_EOL);
245
        }
246
247
        if ($hasCaptures === false) {
248
            $this->console('No captures' . PHP_EOL);
249
        }
250
    }
251
252
    /**
253
     * @param string $string
254
     */
255
    private function console(string $string): void
256
    {
257
        if ($this->isOutputToConsole === true) {
258
            echo $string;
259
        }
260
    }
261
}
262