NOSQLModelDto::toArray()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 11
rs 10
cc 3
nc 4
nop 0
1
<?php
2
namespace NOSQL\Dto\Model;
3
4
use MongoDB\BSON\UTCDateTime;
5
use NOSQL\Exceptions\NOSQLValidationException;
6
use NOSQL\Services\Base\NOSQLBase;
7
use PSFS\base\dto\Dto;
8
use PSFS\base\types\Api;
9
use PSFS\base\types\helpers\InjectorHelper;
10
11
/**
12
 * Class NOSQLModelDto
13
 * @package NOSQL\Dto\Model
14
 */
15
abstract class NOSQLModelDto extends Dto {
16
    /**
17
     * @var string
18
     * @label Model identifier
19
     */
20
    protected $_id;
21
22
    /**
23
     * @var \DateTime
24
     * @label Last update at
25
     */
26
    protected $_last_update;
27
28
29
    /**
30
     * @var string
31
     * @label List name in string
32
     */
33
    protected $__name__;
34
35
    /**
36
     * @return string
37
     */
38
    public function getPk()
39
    {
40
        return $this->_id;
41
    }
42
43
    public function resetPk() {
44
        $this->_id = null;
45
        $this->_last_update = null;
46
    }
47
48
    /**
49
     * @param string $id
50
     * @throws NOSQLValidationException
51
     */
52
    public function setPk(string $id)
53
    {
54
        if(!empty($this->_id)) {
55
            throw new NOSQLValidationException(t('Primary key already defined'), NOSQLValidationException::NOSQL_VALIDATION_ID_ALREADY_DEFINED);
56
        }
57
        $this->_id = $id;
58
    }
59
60
    /**
61
     * @param string $format
62
     * @return \DateTime|string
63
     */
64
    public function getLastUpdate($format = null)
65
    {
66
        $value = $this->_last_update;
67
        if(null !== $format) {
68
69
        }
70
        return $value;
71
    }
72
73
    /**
74
     * @param \DateTime|null $last_update
75
     * @throws \Exception
76
     */
77
    public function setLastUpdate($last_update = null)
78
    {
79
        $this->_last_update = $last_update ?: new UTCDateTime();
0 ignored issues
show
Documentation Bug introduced by
It seems like $last_update ?: new MongoDB\BSON\UTCDateTime() can also be of type MongoDB\BSON\UTCDateTime. However, the property $_last_update is declared as type DateTime. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
80
    }
81
82
    /**
83
     * @return string
84
     */
85
    public function getName()
86
    {
87
        return $this->__name__;
88
    }
89
90
    /**
91
     * @param string $_name__
92
     */
93
    public function setName($_name__)
94
    {
95
        $this->__name__ = $_name__;
96
    }
97
98
    /**
99
     * @param bool $throwException
100
     * @return array
101
     * @throws NOSQLValidationException
102
     * @throws \ReflectionException
103
     */
104
    public function validate($throwException = false) {
105
        $errors = [];
106
        $reflection = new \ReflectionClass(get_called_class());
107
        foreach($reflection->getProperties(\ReflectionProperty::IS_PUBLIC) as $property) {
108
            $required = InjectorHelper::checkIsRequired($property->getDocComment());
109
            $value = $property->getValue($this);
110
            if($required && $this->checkEmpty($value)) {
111
                if($throwException) {
112
                    throw new NOSQLValidationException(t('Empty value for property ') . $property->getName(), NOSQLValidationException::NOSQL_VALIDATION_REQUIRED);
113
                } else {
114
                    $errors[] = $property->getName();
115
                }
116
            } else {
117
                $this->checkType($throwException, $property, $value, $errors);
118
            }
119
        }
120
        return $errors;
121
    }
122
123
    protected function checkEmpty($value) {
124
        return empty($value) && 0 !== $value && '0' !== $value;
125
    }
126
127
    public function toArray()
128
    {
129
        $array = parent::toArray();
130
        if(null !== $this->getPk()) {
0 ignored issues
show
introduced by
The condition null !== $this->getPk() is always true.
Loading history...
131
            $array['_id'] = $this->getPk();
132
        }
133
        if(null !== $this->getName()) {
0 ignored issues
show
introduced by
The condition null !== $this->getName() is always true.
Loading history...
134
            $array[Api::API_LIST_NAME_FIELD] = $this->getName();
135
        }
136
        $array['_last_update'] = $this->getLastUpdate(\DateTime::ATOM);
137
        return $array;
138
    }
139
140
    /**
141
     * @param $throwException
142
     * @param \ReflectionProperty $property
143
     * @param $value
144
     * @param array $errors
145
     * @throws NOSQLValidationException
146
     */
147
    private function checkType($throwException, \ReflectionProperty &$property, $value, array &$errors)
148
    {
149
        $type = InjectorHelper::extractVarType($property->getDocComment());
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $type is correct as PSFS\base\types\helpers\...perty->getDocComment()) targeting PSFS\base\types\helpers\...elper::extractVarType() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
150
        switch (strtolower($type)) {
0 ignored issues
show
Bug introduced by
$type of type null is incompatible with the type string expected by parameter $string of strtolower(). ( Ignorable by Annotation )

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

150
        switch (strtolower(/** @scrutinizer ignore-type */ $type)) {
Loading history...
151
            case NOSQLBase::NOSQL_TYPE_LONG:
152
            case NOSQLBase::NOSQL_TYPE_INTEGER:
153
            case NOSQLBase::NOSQL_TYPE_DOUBLE:
154
                if (!is_numeric($value)) {
155
                    $errors[] = $property->getName();
156
                } else {
157
                    if(NOSQLBase::NOSQL_TYPE_INTEGER === strtolower($type)) {
158
                        $property->setValue($this, (integer)$value);
159
                    } else {
160
                        $property->setValue($this, (float)$value);
161
                    }
162
                }
163
                break;
164
            case NOSQLBase::NOSQL_TYPE_ENUM:
165
                $values = InjectorHelper::getValues($property->getDocComment());
166
                if (!in_array($value, $values)) {
0 ignored issues
show
Bug introduced by
It seems like $values can also be of type null; however, parameter $haystack of in_array() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

166
                if (!in_array($value, /** @scrutinizer ignore-type */ $values)) {
Loading history...
167
                    $errors[] = $property->getName();
168
                }
169
                break;
170
            case NOSQLBase::NOSQL_TYPE_OBJECT:
171
                $property->setValue($this, json_decode($value, true));
172
                break;
173
            case NOSQLBase::NOSQL_TYPE_ARRAY:
174
                if (!is_array($value)) {
175
                    $errors[] = $property->getName();
176
                }
177
                break;
178
            case NOSQLBase::NOSQL_TYPE_BOOLEAN:
179
                if (!in_array($value, [true, false, 0, 1])) {
180
                    $errors[] = $property->getName();
181
                }
182
                $property->setValue($this, (bool)$value);
183
                break;
184
            case NOSQLBase::NOSQL_TYPE_DATE:
185
            case NOSQLBase::NOSQL_TYPE_TIMESTAMP:
186
                $dateTime = new \DateTime($value, new \DateTimeZone('UTC'));
187
                if(!$dateTime) {
0 ignored issues
show
introduced by
$dateTime is of type DateTime, thus it always evaluated to true.
Loading history...
188
                    $errors[] = $property->getName();
189
                } else {
190
                    $dateTime->setTimezone(new \DateTimeZone(date_default_timezone_get()));
191
                    $property->setValue($this, new UTCDateTime($dateTime->getTimestamp()*1000));
192
                }
193
                break;
194
        }
195
        if (in_array($property->getName(), $errors) && $throwException) {
196
            throw new NOSQLValidationException(t('Format not valid for property ') . $property->getName(), NOSQLValidationException::NOSQL_VALIDATION_NOT_VALID);
197
        }
198
    }
199
}