Completed
Push — master ( ffc510...3e9600 )
by Mihail
14:10
created

Model::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Ffcms\Core\Arch;
4
5
use Ffcms\Core\App;
6
use Ffcms\Core\Exception\SyntaxException;
7
use Dflydev\DotAccessData\Data as DotData;
8
use Ffcms\Core\Helper\Type\Obj;
9
use Ffcms\Core\Helper\Type\Str;
10
use Ffcms\Core\Traits\DynamicGlobal;
11
use Ffcms\Core\Traits\ModelValidator;
12
13
class Model
14
{
15
    use DynamicGlobal, ModelValidator;
16
17
    public function __construct()
18
    {
19
        $this->before();
20
    }
21
22
    public function before() {}
23
24
    /**
25
     * Get label value by variable name
26
     * @param string $param
27
     * @return mixed
28
     */
29
    final public function getLabel($param)
30
    {
31
        $labels = $this->labels();
32
        $response = null;
0 ignored issues
show
Unused Code introduced by
$response 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...
33
        // maybe array-dotted declaration?
34
        if (Str::contains('.', $param)) {
35
            // not defined for all array-dotted nesting?
36
            if (Str::likeEmpty($labels[$param])) {
37
                // lets set default array label (before first dot-separation)
38
                $response = $labels[Str::firstIn($param, '.')];
39
            } else {
40
                $response = $labels[$param];
41
            }
42
        } else {
43
            $response = $labels[$param];
44
        }
45
46
        return (Str::likeEmpty($response) ? Str::replace('.', ' ', Str::splitCamelCase($param)) : $response);
47
    }
48
49
    /**
50
     * Set attribute labels for model variables
51
     * @return array
52
     */
53
    public function labels()
54
    {
55
        return [];
56
    }
57
58
    /**
59
     * Set of model validation rules
60
     * @return array
61
     */
62
    public function rules()
63
    {
64
        return [];
65
    }
66
67
    /**
68
     * Set model data sources for input data
69
     * @return array
70
     */
71
    public function sources()
72
    {
73
        return [];
74
    }
75
76
    /**
77
     * Validate defined rules in app
78
     * @return bool
79
     * @throws SyntaxException
80
     */
81
    final public function validate()
82
    {
83
        // get all rules as array from method rules()
84
        $rules = $this->rules();
85
        // get default values of attributes
86
        $defaultAttr = $this->getAllProperties();
87
88
        // start validation as save boolean value
89
        $success = $this->runValidate($rules);
90
91
        // get not-passed validation fields as array
92
        $badAttributes = $this->getBadAttribute();
93
        // prevent warnings
94
        if (Obj::isArray($badAttributes) && count($badAttributes) > 0) {
95
            foreach ($badAttributes as $attr) {
0 ignored issues
show
Bug introduced by
The expression $badAttributes of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
96
                if (Str::contains('.', $attr)) { // sounds like dot-separated array attr
97
                    $attrName = strstr($attr, '.', true); // get attr name
98
                    $attrArray = trim(strstr($attr, '.'), '.'); // get dot-based array path
99
100
                    $defaultValue = new DotData($defaultAttr); // load default attr
101
102
                    $dotData = new DotData($this->{$attrName}); // load local attr variable
103
                    $dotData->set($attrArray, $defaultValue->get($attr)); // set to local prop. variable default value
104
105
                    $this->{$attrName} = $dotData->export(); // export to model
106
                } else {
107
                    $this->{$attr} = App::$Security->strip_tags($defaultAttr[$attr]); // just set ;)
108
                }
109
                // add message about wrong attribute to session holder, later display it
110
                $attrLabel = $attr;
111
                if ($this->getLabel($attr) !== null) {
112
                    $attrLabel = $this->getLabel($attr);
113
                }
114
                App::$Session->getFlashBag()->add('warning', __('Field "%field%" is incorrect', ['field' => $attrLabel]));
115
            }
116
        }
117
118
        return $success;
119
    }
120
121
    /**
122
     * Export model values for safe-using in HTML pages.
123
     * @return $this
124
     */
125
    final public function export()
126
    {
127
        $properties = get_object_vars($this);
128
        foreach ($properties as $var => $value) {
129
            if (Str::startsWith('_', $var)) { // ignore $_var
130
                continue;
131
            }
132
            $this->{$var} = App::$Security->secureHtml($value);
133
        }
134
        return $this;
135
    }
136
137
138
    /**
139
     * Get all properties for current model in key=>value array
140
     * @return array|null
141
     */
142
    public function getAllProperties()
143
    {
144
        $properties = null;
145
        foreach ($this as $property => $value) {
0 ignored issues
show
Bug introduced by
The expression $this of type this<Ffcms\Core\Arch\Model> is not traversable.
Loading history...
146
            if (Str::startsWith('_', $property)) {
147
                continue;
148
            }
149
            $properties[$property] = $value;
150
        }
151
        return $properties;
152
    }
153
154
    /**
155
     * Get validation rules for field
156
     * @param string $field
157
     * @return array
158
     */
159
    final public function getValidationRule($field)
160
    {
161
        $rules = $this->rules();
162
        $response = [];
163
164
        foreach ($rules as $rule) {
165
            if (Obj::isArray($rule[0])) { // 2 or more rules [['field1', 'field2'], 'filter', 'filter_argv']
0 ignored issues
show
Unused Code Comprehensibility introduced by
57% 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...
166
                foreach ($rule[0] as $tfield) {
167
                    if ($tfield == $field) {
168
                        $response[$rule[1]] = $rule[2]; // ['min_length' => 1, 'required' => 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...
169
                    }
170
                }
171
            } else { // 1 rule ['field1', 'filter', 'filter_argv']
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% 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...
172
                if ($rule[0] === $field) {
173
                    $response[$rule[1]] = $rule[2];
174
                }
175
            }
176
        }
177
178
        return $response;
179
    }
180
181
}