Issues (38)

Security Analysis    not enabled

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/Traits/MultiUnitSupport.php (20 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 MaksimM\MultiUnitModels\Traits;
4
5
use Illuminate\Database\Eloquent\Model;
6
use Illuminate\Support\Arr;
7
use MaksimM\MultiUnitModels\Exceptions\NotSupportedMultiUnitField;
8
use MaksimM\MultiUnitModels\Exceptions\NotSupportedMultiUnitFieldUnit;
9
use UnitConverter\Unit\AbstractUnit;
10
11
trait MultiUnitSupport
12
{
13
    use ModelConfiguration;
14
15
    protected $unitConversionDataPostfix = '_ucd';
16
    protected $multiUnitColumns = [];
17
    protected $multiUnitSelectedUnits = [];
18
19
    private function getUnitConversionDataColumns()
0 ignored issues
show
This method is not used, and could be removed.
Loading history...
20
    {
21
        return array_map(function ($column) {
22
            return $column.$this->getUnitConversionDataPostfix();
23
        }, array_keys($this->getMultiUnitColumns()));
24
    }
25
26
    protected static function bootMultiUnitSupport()
27
    {
28
        //save conversion table if base value is changed
29
        static::creating(function ($model) {
30
            /**
31
             * @var Model|MultiUnitSupport $model
32
             */
33
            foreach ($model->getMultiUnitColumns() as $unitBasedColumn => $options) {
0 ignored issues
show
The method getMultiUnitColumns does only exist in MaksimM\MultiUnitModels\Traits\MultiUnitSupport, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
34
                if (isset($model->attributes[$unitBasedColumn])) {
35
                    $model->{$unitBasedColumn.$model->getUnitConversionDataPostfix()} = json_encode(
0 ignored issues
show
The method getUnitConversionDataPostfix does only exist in MaksimM\MultiUnitModels\Traits\MultiUnitSupport, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
36
                        $model->calculateMultiUnitConversionData(
0 ignored issues
show
The method calculateMultiUnitConversionData does only exist in MaksimM\MultiUnitModels\Traits\MultiUnitSupport, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
37
                            $model->attributes[$unitBasedColumn],
38
                            $model->getMultiUnitFieldUnit($unitBasedColumn),
0 ignored issues
show
The method getMultiUnitFieldUnit does only exist in MaksimM\MultiUnitModels\Traits\MultiUnitSupport, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
39
                            $options['supported_units']
40
                        )
41
                    );
42
                    $model->attributes[$unitBasedColumn] = $model->processMultiUnitFieldChanges(
0 ignored issues
show
The method processMultiUnitFieldChanges does only exist in MaksimM\MultiUnitModels\Traits\MultiUnitSupport, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
43
                        $unitBasedColumn,
44
                        $model->{$unitBasedColumn}
45
                    );
46
                }
47
            }
48
        });
49
        static::updating(function ($model) {
50
            /**
51
             * @var Model|MultiUnitSupport $model
52
             */
53
            foreach (Arr::only($model->getMultiUnitColumns(), array_keys($model->getDirty())) as $unitBasedColumn => $options) {
0 ignored issues
show
The method getMultiUnitColumns does only exist in MaksimM\MultiUnitModels\Traits\MultiUnitSupport, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
The method getDirty does only exist in Illuminate\Database\Eloquent\Model, but not in MaksimM\MultiUnitModels\Traits\MultiUnitSupport.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
54
                $newValue = $model->attributes[$unitBasedColumn];
55
                $newValueInDefaultUnits = $model->processMultiUnitFieldChanges(
0 ignored issues
show
The method processMultiUnitFieldChanges does only exist in MaksimM\MultiUnitModels\Traits\MultiUnitSupport, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
56
                    $unitBasedColumn,
57
                    $newValue
58
                );
59
                $model->{$unitBasedColumn.$model->getUnitConversionDataPostfix()} = json_encode(
0 ignored issues
show
The method getUnitConversionDataPostfix does only exist in MaksimM\MultiUnitModels\Traits\MultiUnitSupport, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
60
                    $model->calculateMultiUnitConversionData(
0 ignored issues
show
The method calculateMultiUnitConversionData does only exist in MaksimM\MultiUnitModels\Traits\MultiUnitSupport, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
61
                        $newValue,
62
                        $model->getMultiUnitFieldUnit($unitBasedColumn),
0 ignored issues
show
The method getMultiUnitFieldUnit does only exist in MaksimM\MultiUnitModels\Traits\MultiUnitSupport, but not in Illuminate\Database\Eloquent\Model.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
63
                        $options['supported_units']
64
                    )
65
                );
66
                $model->attributes[$unitBasedColumn] = $newValueInDefaultUnits;
67
            }
68
        });
69
    }
70
71
    /**
72
     * @param              $value
73
     * @param AbstractUnit $unit
74
     * @param string[]     $requiredUnits
75
     *
76
     * @return array|null
77
     */
78
    private function calculateMultiUnitConversionData($value, AbstractUnit $unit, $requiredUnits)
79
    {
80
        if (is_null($value)) {
81
            return;
82
        }
83
84
        $conversionData = [];
85
        foreach ($requiredUnits as $requiredUnitClass) {
86
            /**
87
             * @var AbstractUnit $requiredUnit
88
             */
89
            $requiredUnit = new $requiredUnitClass();
90
            $conversionData[$requiredUnit->getId()] = (new $unit($value))->as($requiredUnit);
91
        }
92
93
        return $conversionData;
94
    }
95
96
    public function getMultiUnitExistingConversionData($field)
0 ignored issues
show
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
97
    {
98
        return json_decode($this->{$field.$this->getUnitConversionDataPostfix()} ?? null);
99
    }
100
101
    /**
102
     * @return string
103
     */
104
    protected function getUnitConversionDataPostfix()
105
    {
106
        return $this->unitConversionDataPostfix;
107
    }
108
109
    /**
110
     * @return array
111
     */
112
    public function getMultiUnitColumns()
113
    {
114
        return $this->multiUnitColumns;
115
    }
116
117
    /**
118
     * @param $field
119
     *
120
     * @throws NotSupportedMultiUnitField
121
     *
122
     * @return AbstractUnit[]
123
     */
124
    public function getMultiUnitFieldSupportedUnits($field)
125
    {
126
        if ($this->isMultiUnitField($field)) {
127
            return $this->getMultiUnitColumns()[$field]['supported_units'];
128
        }
129
130
        throw new NotSupportedMultiUnitField($field);
131
    }
132
133
    /**
134
     * @param $field
135
     *
136
     * @throws NotSupportedMultiUnitField
137
     *
138
     * @return AbstractUnit
139
     */
140
    public function getMultiUnitFieldDefaultUnit($field)
141
    {
142
        if ($this->isMultiUnitField($field)) {
143
            $unitClass = $this->getMultiUnitColumns()[$field]['default_unit'];
144
145
            return new $unitClass();
146
        }
147
148
        throw new NotSupportedMultiUnitField($field);
149
    }
150
151
    /**
152
     * @param $field
153
     *
154
     * @throws NotSupportedMultiUnitField
155
     *
156
     * @return AbstractUnit
157
     */
158
    public function getMultiUnitFieldSelectedUnit($field)
159
    {
160
        if ($this->isMultiUnitField($field)) {
161
            $unitClass = $this->multiUnitSelectedUnits[$field] ?? $this->getMultiUnitFieldDefaultUnit($field);
162
163
            return new $unitClass();
164
        }
165
166
        throw new NotSupportedMultiUnitField($field);
167
    }
168
169
    /**
170
     * @param $field
171
     * @param string $unit
172
     *
173
     * @throws NotSupportedMultiUnitField
174
     * @throws NotSupportedMultiUnitFieldUnit
175
     */
176
    public function setMultiUnitFieldSelectedUnit($field, $unit)
177
    {
178
        if ($this->isMultiUnitField($field)) {
179
            $found = false;
180 View Code Duplication
            foreach ($this->getMultiUnitFieldSupportedUnits($field) as $unitClass) {
0 ignored issues
show
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...
181
                /**
182
                 * @var AbstractUnit $unit
183
                 */
184
                $supportedUnit = new $unitClass();
185
                if (strtolower($supportedUnit->getId()) == strtolower($unit)) {
186
                    $found = true;
187
                    break;
188
                }
189
            }
190
            if ($found) {
191
                $this->multiUnitSelectedUnits[$field] = $unitClass;
0 ignored issues
show
The variable $unitClass seems to be defined by a foreach iteration on line 180. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
192
            } else {
193
                throw new NotSupportedMultiUnitFieldUnit($field, $unit);
194
            }
195
        } else {
196
            throw new NotSupportedMultiUnitField($field);
197
        }
198
    }
199
200
    /**
201
     * @param        $field
202
     * @param string $unit
0 ignored issues
show
Should the type for parameter $unit not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
203
     *
204
     * @throws NotSupportedMultiUnitField
205
     *
206
     * @return mixed
207
     */
208
    public function getMultiUnitFieldValueByUnitName($field, $unit = null)
209
    {
210
        if ($this->isMultiUnitField($field)) {
211
            if (isset($this->{$field})) {
212
                if (is_null($unit)) {
213
                    $unit = $this->getMultiUnitFieldUnit($field);
214
                } else {
215 View Code Duplication
                    foreach ($this->getMultiUnitFieldSupportedUnits($field) as $unitClass) {
0 ignored issues
show
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...
216
                        /**
217
                         * @var AbstractUnit $unit
218
                         */
219
                        $supportedUnit = new $unitClass();
220
                        if (strtolower($supportedUnit->getId()) == strtolower($unit)) {
221
                            $unit = $supportedUnit;
222
                            break;
223
                        }
224
                    }
225
                }
226
                if (is_string($unit)) {
227
                    throw new NotSupportedMultiUnitField($field);
228
                }
229
                $existingConversionData = $this->getMultiUnitExistingConversionData($field);
230 View Code Duplication
                if (!is_null($existingConversionData) && !is_null($existingConversionData->{$unit->getId()})) {
0 ignored issues
show
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...
231
                    return $existingConversionData->{$unit->getId()};
232
                }
233
234
                return ($this->getMultiUnitFieldSelectedUnit($field)->setValue($this->{$field} ?? $this->attributes[$field]))->as(new $unit());
0 ignored issues
show
The property attributes does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
235
            } else {
236
                return;
237
            }
238
        }
239
240
        throw new NotSupportedMultiUnitField($field);
241
    }
242
243
    /**
244
     * @param                   $field
245
     * @param AbstractUnit|null $unit
246
     *
247
     * @throws NotSupportedMultiUnitField
248
     *
249
     * @return mixed
250
     */
251
    public function getMultiUnitFieldValue($field, AbstractUnit $unit = null)
252
    {
253
        if ($this->isMultiUnitField($field)) {
254
            if (isset($this->{$field})) {
255
                if (is_null($unit)) {
256
                    $unit = $this->getMultiUnitFieldUnit($field);
257
                }
258
                $existingConversionData = $this->getMultiUnitExistingConversionData($field);
259 View Code Duplication
                if (!is_null($existingConversionData) && !is_null($existingConversionData->{$unit->getId()})) {
0 ignored issues
show
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...
260
                    return $existingConversionData->{$unit->getId()};
261
                }
262
263
                return ($this->getMultiUnitFieldSelectedUnit($field)->setValue($this->{$field} ?? $this->attributes[$field]))->as(new $unit());
264
            } else {
265
                return;
266
            }
267
        }
268
269
        throw new NotSupportedMultiUnitField($field);
270
    }
271
272
    protected function isMultiUnitField($field)
273
    {
274
        return isset($this->getMultiUnitColumns()[$field]);
275
    }
276
277
    /**
278
     * @param $field
279
     *
280
     * @throws NotSupportedMultiUnitField
281
     *
282
     * @return AbstractUnit
283
     */
284
    protected function getMultiUnitFieldUnit($field, $preferDefault = false)
285
    {
286
        return $preferDefault ? $this->getMultiUnitFieldDefaultUnit($field) : $this->getMultiUnitFieldSelectedUnit($field);
287
    }
288
}
289