Completed
Push — master ( 386a3a...dd6ab7 )
by Mihail
02:44
created

ModelValidator::getFormName()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 9
rs 9.6667
cc 2
eloc 5
nc 2
nop 0
1
<?php
2
3
namespace Ffcms\Core\Traits;
4
5
6
use Ffcms\Core\App;
7
use Ffcms\Core\Exception\SyntaxException;
8
use Ffcms\Core\Filter\Native;
9
use Ffcms\Core\Helper\Type\Obj;
10
use Ffcms\Core\Helper\Type\Str;
11
use Dflydev\DotAccessData\Data as DotData;
12
13
trait ModelValidator
14
{
15
    protected $_badAttr;
16
    protected $_sendMethod = 'POST';
17
18
    protected $_formName;
19
20
    public function runValidate(array $rules = null)
21
    {
22
        // skip validation on empty rules
23
        if ($rules === null) {
24
            return true;
25
        }
26
27
        $success = true;
28
        // each
29
        foreach ($rules as $rule) {
30
            // 0 = name, 1 = filter name, 2 = filter value
31
            if ($rule[0] === null || $rule[1] === null) {
32
                continue;
33
            }
34
35
            if (Obj::isArray($rule[0])) {
36
                $validate_foreach = true;
37
                foreach ($rule[0] as $field_name) {
38
                    // end false condition
39
                    if (!$this->validateRecursive($field_name, $rule[1], $rule[2], $rule[3], $rule[4])) {
40
                        $validate_foreach = false;
41
                    }
42
                }
43
                // assign total
44
                $validate = $validate_foreach;
45
            } else {
46
                $validate = $this->validateRecursive($rule[0], $rule[1], $rule[2], $rule[3], $rule[4]);
47
            }
48
49
            // do not change condition on "true" check's (end-false-condition)
50
            if ($validate === false) {
51
                $success = false;
52
            }
53
        }
54
55
        return $success;
56
    }
57
58
    /**
59
     * @param $field_name
60
     * @param $filter_name
61
     * @param $filter_argv
62
     * @param bool $html
63
     * @param bool $secure
64
     * @return bool
65
     * @throws SyntaxException
66
     */
67
    public function validateRecursive($field_name, $filter_name, $filter_argv, $html = false, $secure = false)
68
    {
69
        // check if we got it from form defined request method
70
        if (App::$Request->getMethod() !== $this->_sendMethod) {
71
            return false;
72
        }
73
74
        $inputTypes = [];
75
        // check input data type. Maybe file or input (text)
76
        if (method_exists($this, 'inputTypes')) {
77
            $inputTypes = $this->inputTypes();
78
        }
79
80
        // sounds like file
81
        if ($inputTypes[$field_name] === 'file') {
82
            $field_value = $this->getFile($field_name);
83
        } else { // sounds like plain post data
84
            $field_value = $this->getInput($field_name);
85
            // remove or safe use html
86
            if ($html === false) {
87
                $field_value = App::$Security->strip_tags($field_value);
88
            } else {
89
                if ($secure !== true) {
90
                    $field_value = App::$Security->secureHtml($field_value);
91
                }
92
            }
93
        }
94
95
        $check = false;
0 ignored issues
show
Unused Code introduced by
$check is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
96
        // maybe no filter required?
97
        if ($filter_name === 'used') {
98
            $check = true;
99
        } elseif (Str::contains('::', $filter_name)) { // sounds like a callback class::method::method
100
            // string to array via delimiter ::
101
            $callbackArray = explode('::', $filter_name);
102
            // first item is a class name
103
            $class = array_shift($callbackArray);
104
            // last item its a function
105
            $method = array_pop($callbackArray);
106
            // left any items? maybe post-static callbacks?
107
            if (count($callbackArray) > 0) {
108
                foreach ($callbackArray as $obj) {
109
                    if (Str::startsWith('$', $obj) && property_exists($class, ltrim($obj, '$'))) { // sounds like a variable
110
                        $obj = ltrim($obj, '$'); // trim variable symbol '$'
111
                        $class = $class::$$obj; // make magic :)
112
                    } elseif (method_exists($class, $obj)) { // maybe its a function?
113
                        $class = $class::$obj; // call function
114
                    } else {
115
                        throw new SyntaxException('Filter callback execution failed: ' . $filter_name);
116
                    }
117
118
                }
119
            }
120
121
            // check is endpoint method exist
122
            if (method_exists($class, $method)) {
123
                $check = @$class::$method($field_value, $filter_argv);
124
            } else {
125
                throw new SyntaxException('Filter callback execution failed: ' . $filter_name);
126
            }
127
        } elseif (method_exists('Ffcms\Core\Filter\Native', $filter_name)) { // only full namespace\class path based :(
128
            if ($filter_argv != null) {
129
                $check = Native::$filter_name($field_value, $filter_argv);
130
            } else {
131
                $check = Native::$filter_name($field_value);
132
            }
133
        } else {
134
            throw new SyntaxException('Filter "' . $filter_name . '" is not exist');
135
        }
136
        if ($check !== true) { // switch only on fail check.
137
            $this->_badAttr[] = $field_name;
138
        } else {
139
            $field_set_name = $field_name;
140
            // prevent array-type setting
141
            if (Str::contains('.', $field_set_name)) {
142
                $field_set_name = strstr($field_set_name, '.', true);
143
            }
144
            if (property_exists($this, $field_set_name)) {
145
                if ($field_name !== $field_set_name) { // array-based property
146
                    $dot_path = trim(strstr($field_name, '.'), '.');
147
                    // prevent throws any exceptions for null and false objects
148
                    if (!Obj::isArray($this->{$field_set_name})) {
149
                        $this->{$field_set_name} = [];
150
                    }
151
                    // use dot-data provider to compile output array
152
                    $dotData = new DotData($this->{$field_set_name});
153
                    $dotData->set($dot_path, $field_value); // todo: check me!!! bug here
154
                    // export data from dot-data lib to model property
155
                    $this->{$field_set_name} = $dotData->export();
156
                } else { // just single property
157
                    $this->{$field_name} = $field_value; // refresh model property's from post data
158
                }
159
            }
160
        }
161
        return $check;
162
    }
163
164
    /**
165
     * Get fail validation attributes as array if exist
166
     * @return null|array
167
     */
168
    public function getBadAttribute()
169
    {
170
        return $this->_badAttr;
171
    }
172
173
    /**
174
     * Set model send method type. Allowed: post, get
175
     * @param string $acceptMethod
176
     */
177
    final public function setSubmitMethod($acceptMethod)
178
    {
179
        $this->_sendMethod = strtoupper($acceptMethod);
180
    }
181
182
    /**
183
     * Get model submit method. Allowed: post, get
184
     * @return string
185
     */
186
    final public function getSubmitMethod()
187
    {
188
        return $this->_sendMethod;
189
    }
190
191
    /**
192
     * Check if model get POST-based request as submit of SEND data
193
     * @return bool
194
     */
195
    final public function send()
196
    {
197
        if (App::$Request->getMethod() !== $this->_sendMethod) {
198
            return false;
199
        }
200
201
        return null !== $this->getInput('submit');
202
    }
203
204
    /**
205
     * Form default name (used in field building)
206
     * @return string
207
     */
208
    public function getFormName()
209
    {
210
        if (null === $this->_formName) {
211
            $cname = get_class($this);
212
            $this->_formName = substr($cname, strrpos($cname, '\\') + 1);
213
        }
214
215
        return $this->_formName;
216
    }
217
218
    /**
219
     * Get input params GET/POST/PUT method
220
     * @param string $param
221
     * @return string|null
222
     */
223 View Code Duplication
    public function getInput($param)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
224
    {
225
        $objName = $this->getFormName();
226
        if (Str::contains('.', $param)) {
227
            foreach (explode('.', $param) as $item) {
228
                $objName .= '[' . $item . ']';
229
            }
230
        } else {
231
            $objName .= '[' . $param . ']';
232
        }
233
        return App::$Request->get($objName, null, true);
234
    }
235
236
    /**
237
     * Get uploaded file from user via POST request
238
     * @param string $param
239
     * @return \Symfony\Component\HttpFoundation\File\UploadedFile|null
240
     */
241 View Code Duplication
    public function getFile($param)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
242
    {
243
        $fileName = $this->getFormName();
244
        if (Str::contains('.', $param)) {
245
            foreach (explode('.', $param) as $obj) {
246
                $fileName .= '[' . $obj . ']';
247
            }
248
        } else {
249
            $fileName .= '[' . $param . ']';
250
        }
251
        return App::$Request->files->get($fileName, null, true);
252
    }
253
254
    /**
255
     * Set special type for input data. Example: ['avatar' => 'file', 'login' => 'input']
256
     * @return array
257
     */
258
    public function inputTypes()
259
    {
260
        return [];
261
    }
262
}