Issues (107)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Validable.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Sofa\Eloquence;
4
5
use Sofa\Eloquence\Validable\Observer;
6
use Illuminate\Contracts\Validation\Factory;
7
8
/**
9
 * @method integer getKey()
10
 * @method string getKeyName()
11
 */
12
trait Validable
13
{
14
    /**
15
     * Validation switch.
16
     *
17
     * @var boolean
18
     */
19
    protected $skipValidation = false;
20
21
    /**
22
     * Validator instance.
23
     *
24
     * @var \Illuminate\Contracts\Validation\Validator
25
     */
26
    protected $validator;
27
28
    /**
29
     * Validator factory instance.
30
     *
31
     * @var \Illuminate\Contracts\Validation\Factory
32
     */
33
    protected static $validatorFactory;
34
35
    /**
36
     * All the validation rules for this model.
37
     *
38
     * @var array
39
     */
40
    protected static $rulesMerged;
41
42
    /**
43
     * Register hooks for the trait.
44
     *
45
     * @codeCoverageIgnore
46
     *
47
     * @return void
48
     */
49
    public static function bootValidable()
50
    {
51
        static::observe(new Observer);
52
53
        if (!static::$validatorFactory) {
54
            if (function_exists('app') && app()->bound('validator')) {
55
                static::setValidatorFactory(app('validator'));
56
            }
57
        }
58
    }
59
60
    /**
61
     * Determine whether all the attributes on this instance pass validation.
62
     *
63
     * @return boolean
64
     */
65
    public function isValid()
66
    {
67
        $this->getValidator()->setData($this->getAttributes());
0 ignored issues
show
It seems like getAttributes() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
The method setData() does not seem to exist on object<Illuminate\Contracts\Validation\Validator>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
68
69
        return $this->getValidator()->passes();
0 ignored issues
show
The method passes() does not seem to exist on object<Illuminate\Contracts\Validation\Validator>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
70
    }
71
72
    /**
73
     * Skip validation on the next saving attempt.
74
     *
75
     * @return $this
76
     */
77
    public function skipValidation()
78
    {
79
        return $this->disableValidation($once = true);
80
    }
81
82
    /**
83
     * Disable validation for this instance.
84
     *
85
     * @return $this
86
     */
87
    public function disableValidation($once = false)
88
    {
89
        $this->skipValidation = ($once) ? Observer::SKIP_ONCE : Observer::SKIP_ALWAYS;
90
91
        return $this;
92
    }
93
94
    /**
95
     * Enable validation for this instance.
96
     *
97
     * @return $this
98
     */
99
    public function enableValidation()
100
    {
101
        $this->skipValidation = false;
102
103
        return $this;
104
    }
105
106
    /**
107
     * Get current validation flag.
108
     *
109
     * @return integer|false
110
     */
111
    public function skipsValidation()
112
    {
113
        return $this->skipValidation;
114
    }
115
116
    /**
117
     * Determine whether validation is enabled for this instance.
118
     *
119
     * @return boolean
120
     */
121
    public function validationEnabled()
122
    {
123
        return !$this->skipsValidation();
124
    }
125
126
    /**
127
     * Retrieve validation error messages.
128
     *
129
     * @return \Illuminate\Support\MessageBag
130
     */
131
    public function getValidationErrors()
132
    {
133
        return $this->getMessageBag();
134
    }
135
136
    /**
137
     * Retrieve validation error messages.
138
     *
139
     * @return \Illuminate\Support\MessageBag
140
     */
141
    public function getMessageBag()
142
    {
143
        return $this->getValidator()->getMessageBag();
144
    }
145
146
    /**
147
     * Get names of the attributes that didn't pass validation.
148
     *
149
     * @return array
150
     */
151
    public function getInvalidAttributes()
152
    {
153
        return array_keys($this->getValidationErrors()->toArray());
154
    }
155
156
    /**
157
     * Get the validator instance.
158
     *
159
     * @return \Illuminate\Contracts\Validation\Validator
160
     */
161
    public function getValidator()
162
    {
163
        if (!$this->validator) {
164
            $this->validator = static::$validatorFactory->make(
165
                [],
166
                static::getCreateRules(),
167
                static::getValidationMessages(),
168
                static::getValidationAttributes()
169
            );
170
        }
171
172
        return $this->validator;
173
    }
174
175
    /**
176
     * Get custom validation messages.
177
     *
178
     * @return array
179
     */
180
    public static function getValidationMessages()
181
    {
182
        return (property_exists(get_called_class(), 'validationMessages'))
183
            ? static::$validationMessages
184
            : [];
185
    }
186
187
    /**
188
     * Get custom validation attribute names.
189
     *
190
     * @return array
191
     */
192
    public static function getValidationAttributes()
193
    {
194
        return (property_exists(get_called_class(), 'validationAttributes'))
195
            ? static::$validationAttributes
196
            : [];
197
    }
198
199
    /**
200
     * Get all the validation rules for this model.
201
     *
202
     * @return array
203
     */
204
    public static function getCreateRules()
205
    {
206
        if (!static::$rulesMerged) {
207
            static::$rulesMerged = static::gatherRules();
208
        }
209
210
        return static::$rulesMerged;
211
    }
212
213
    /**
214
     * Gather all the rules for the model and store it for easier use.
215
     *
216
     * @return array
217
     */
218
    protected static function gatherRules()
219
    {
220
        // This rather gnarly looking logic is just for developer convenience
221
        // so he can define multiple rule groups on the model for clarity
222
        // and now we simply gather all rules and merge them together.
223
        $keys = static::getValidatedFields();
224
225
        $result = array_fill_keys($keys, []);
226
227
        foreach ($keys as $key) {
228
            foreach (static::getRulesGroups() as $groupName) {
229
                $group = static::getRulesGroup($groupName);
230
231
                if (isset($group[$key])) {
232
                    $rules = is_array($group[$key])
233
                            ? $group[$key]
234
                            : explode('|', $group[$key]);
235
236
                    foreach ($rules as &$rule) {
237
                        if ($rule === 'unique') {
238
                            $table = (new static)->getTable();
0 ignored issues
show
It seems like getTable() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
239
240
                            $rule .= ":{$table}";
241
                        }
242
                    }
243
244
                    unset($rule);
245
246
                    $result[$key] = array_unique(array_merge($result[$key], $rules));
247
                }
248
            }
249
        }
250
251
        return $result;
252
    }
253
254
    /**
255
     * Get all validation rules for update on this model.
256
     *
257
     * @return array
258
     */
259
    public function getUpdateRules()
260
    {
261
        return ($this->getKey()) ? static::getUpdateRulesForId($this) : static::getCreateRules();
262
    }
263
264
    /**
265
     * Get all validation rules for update for given id.
266
     *
267
     * @param  \Illuminate\Database\Eloquent\Model|integer|string $id
268
     * @return array
269
     */
270
    public static function getUpdateRulesForId($id)
271
    {
272
        return rules_for_update(static::getCreateRules(), $id, (new static)->getKeyName());
273
    }
274
275
    /**
276
     * Get array of attributes that have validation rules defined.
277
     *
278
     * @return array
279
     */
280
    public static function getValidatedFields()
281
    {
282
        $fields = [];
283
284
        foreach (static::getRulesGroups() as $groupName) {
285
            $fields = array_merge($fields, array_keys(static::getRulesGroup($groupName)));
286
        }
287
288
        return array_values(array_unique($fields));
289
    }
290
291
    /**
292
     * Get all the rules groups defined on this model.
293
     *
294
     * @return array
295
     */
296
    protected static function getRulesGroups()
297
    {
298
        $groups = [];
299
300
        foreach (get_class_vars(get_called_class()) as $property => $val) {
301
            if (preg_match('/^.*rules$/i', $property)) {
302
                $groups[] = $property;
303
            }
304
        }
305
306
        return $groups;
307
    }
308
309
    /**
310
     * Get rules from given group.
311
     *
312
     * @param  string $group
313
     * @return array
314
     */
315
    protected static function getRulesGroup($group)
316
    {
317
        return static::$$group;
318
    }
319
320
    /**
321
     * Set validation factory instance for this model.
322
     *
323
     * @param  \Illuminate\Contracts\Validation\Factory
324
     * @return void
325
     */
326
    public static function setValidatorFactory(Factory $factory)
327
    {
328
        static::$validatorFactory = $factory;
329
    }
330
}
331