Passed
Push — master ( 956756...b9396f )
by Mihail
04:20
created

Model::getLabel()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 6
nop 1
dl 0
loc 18
rs 9.2
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A Model::rules() 0 3 1
1
<?php
2
3
namespace Ffcms\Core\Arch;
4
5
use Dflydev\DotAccessData\Data as DotData;
6
use Ffcms\Core\App;
7
use Ffcms\Core\Exception\SyntaxException;
8
use Ffcms\Core\Helper\Type\Any;
9
use Ffcms\Core\Helper\Type\Str;
10
use Ffcms\Core\Interfaces\iModel;
11
use Ffcms\Core\Traits\ModelValidator;
12
use Ffcms\Templex\Helper\Html\Form\ModelInterface;
0 ignored issues
show
Bug introduced by
The type Ffcms\Templex\Helper\Html\Form\ModelInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use Ffcms\Templex\Helper\Html\Form\Model as TemplexModel;
0 ignored issues
show
Bug introduced by
The type Ffcms\Templex\Helper\Html\Form\Model was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
15
/**
16
 * Class Model. Classic constructor of models in MVC architecture with algorithm of passing attributes from user input data.
17
 * @package Ffcms\Core\Arch
18
 */
19
abstract class Model extends TemplexModel implements iModel, ModelInterface
20
{
21
    use ModelValidator {
22
        ModelValidator::initialize as private validatorConstructor;
23
    }
24
25
    public $_csrf_token;
26
27
    /**
28
     * Model constructor. Initialize before() method for extended objects and run validator initialization
29
     * @param bool $csrf
30
     */
31
    public function __construct($csrf = false)
32
    {
33
        $this->before();
34
        $this->validatorConstructor($csrf);
35
        parent::__construct();
36
    }
37
38
    /**
39
     * Make any things before model is initialized
40
     */
41
    public function before() {}
42
43
    /**
44
     * Set attribute labels for model variables
45
     * @return array
46
     */
47
    public function labels(): array
48
    {
49
        return [];
50
    }
51
52
    /**
53
     * Set of model validation rules
54
     * @return array
55
     */
56
    public function rules(): array
57
    {
58
        return [];
59
    }
60
61
    /**
62
     * Set model data sources for input data
63
     * Allowed sources: get, post, file
64
     * @return array
65
     */
66
    public function sources(): array
67
    {
68
        return [];
69
    }
70
71
    /**
72
     * Set model property types to advanced filtering
73
     * Allowed types: text, html, !secure
74
     * Ex: ['property1' => 'text', 'property2' => 'html']
75
     * @return array
76
     */
77
    public function types(): array
78
    {
79
        return [];
80
    }
81
82
    /**
83
     * Validate defined rules in app
84
     * @return bool
85
     * @throws SyntaxException
86
     */
87
    final public function validate(): bool
88
    {
89
        // validate csrf token if required
90
        if ($this->_tokenRequired && !$this->_tokenOk) {
91
            App::$Session->getFlashBag()->add('warning', __('Hack attention: security token is wrong!'));
0 ignored issues
show
Bug introduced by
The function __ was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

91
            App::$Session->getFlashBag()->add('warning', /** @scrutinizer ignore-call */ __('Hack attention: security token is wrong!'));
Loading history...
92
            return false;
93
        }
94
        // get all rules as array from method rules()
95
        $rules = $this->rules();
96
        // get default values of attributes
97
        $defaultAttr = $this->getAllProperties();
98
99
        // start validation: on this step class attribute values will be changed to input data if it valid
100
        $success = $this->runValidate($rules);
101
102
        // get not-passed validation fields as array
103
        $badAttributes = $this->getBadAttribute();
104
        // prevent warnings
105
        if (Any::isArray($badAttributes) && count($badAttributes) > 0) {
106
            foreach ($badAttributes as $attr) {
107
                if (Str::contains('.', $attr)) { // sounds like dot-separated array attr
108
                    $attrName = strstr($attr, '.', true); // get attr name
109
                    $attrArray = trim(strstr($attr, '.'), '.'); // get dot-based array path
110
111
                    $defaultValue = new DotData($defaultAttr); // load default attr
112
113
                    $dotData = new DotData($this->{$attrName}); // load local attr variable
114
                    $dotData->set($attrArray, $defaultValue->get($attr)); // set to local prop. variable default value
115
116
                    $this->{$attrName} = $dotData->export(); // export to model
117
                } else {
118
                    $this->{$attr} = $defaultAttr[$attr]; // just set ;)
119
                }
120
                // add message about wrong attribute to session holder, later display it
121
                $attrLabel = $attr;
122
                if ($this->getLabel($attr) !== null) {
123
                    $attrLabel = $this->getLabel($attr);
124
                }
125
126
                App::$Session->getFlashBag()->add('warning', __('Field "%field%" is incorrect', ['field' => $attrLabel]));
127
            }
128
        }
129
130
        return $success;
131
    }
132
133
    /**
134
     * Get all properties for current model in key=>value array
135
     * @return array|null
136
     */
137
    public function getAllProperties(): ?array
138
    {
139
        $properties = null;
140
        // list all properties here, array_walk sucks on performance!
141
        foreach ($this as $property => $value) {
142
            if (Str::startsWith('_', $property)) {
143
                continue;
144
            }
145
146
            $properties[$property] = $value;
147
        }
148
        return $properties;
149
    }
150
151
    /**
152
     * Cleanup all public model properties
153
     * @return void
154
     */
155
    public function clearProperties(): void
156
    {
157
        foreach ($this as $property => $value) {
158
            if (!Str::startsWith('_', $property)) {
159
                $this->{$property} = null;
160
            }
161
        }
162
    }
163
164
    /**
165
     * Get validation rules for field
166
     * @param string $field
167
     * @return array
168
     */
169
    final public function getValidationRule($field): array
170
    {
171
        $rules = $this->rules();
172
        $response = [];
173
174
        foreach ($rules as $rule) {
175
            if (Any::isArray($rule[0])) { // 2 or more rules [['field1', 'field2'], 'filter', 'filter_argv']
176
                foreach ($rule[0] as $tfield) {
177
                    if ($tfield == $field) {
178
                        $response[$rule[1]] = $rule[2];
179
                    } // ['min_length' => 1, 'required' => null]
180
                }
181
            } else { // 1 rule ['field1', 'filter', 'filter_argv']
182
                if ($rule[0] === $field) {
183
                    $response[$rule[1]] = $rule[2];
184
                }
185
            }
186
        }
187
188
        return $response;
189
    }
190
}
191