ModelDeserialiser::bulkDeserialise()   D
last analyzed

Complexity

Conditions 18
Paths 20

Size

Total Lines 78
Code Lines 53

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 18
eloc 53
c 1
b 1
f 0
nc 20
nop 2
dl 0
loc 78
rs 4.8666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace POData\ObjectModel;
6
7
use DateTime;
8
use DateTimeZone;
9
use Exception;
10
use InvalidArgumentException;
11
use POData\Providers\Metadata\ResourceEntityType;
12
13
/**
14
 * Class ModelDeserialiser.
15
 * @package POData\ObjectModel
16
 */
17
class ModelDeserialiser
18
{
19
    // take a supplied resourceEntityType and ODataEntry object, check that they match, and retrieve the
20
    // non-key properties for same
21
22
    private static $nonKeyPropertiesCache = [];
23
24
    public function __construct()
25
    {
26
    }
27
28
    /**
29
     * Filter supplied ODataEntry into $data array for use in resource create/update.
30
     *
31
     * @param ResourceEntityType $entityType Entity type to deserialise to
32
     * @param ODataEntry         $payload    Raw data to deserialise
33
     *
34
     * @throws Exception
35
     * @throws InvalidArgumentException
36
     * @return mixed[]
37
     */
38
    public function bulkDeserialise(ResourceEntityType $entityType, ODataEntry $payload)
39
    {
40
        if (!isset($payload->type)) {
41
            $msg = 'ODataEntry payload type not set';
42
            throw new InvalidArgumentException($msg);
43
        }
44
45
        /** @scrutinizer ignore-call */
46
        $payloadType = $payload->type->getTerm();
47
        $pay         = explode('.', $payloadType);
48
        $payloadType = $pay[count($pay) - 1];
49
        $actualType  = $entityType->getName();
50
51
        if ($payloadType !== $actualType) {
52
            $msg = 'Payload resource type does not match supplied resource type.';
53
            throw new InvalidArgumentException($msg);
54
        }
55
56
        if (!isset(self::$nonKeyPropertiesCache[$actualType])) {
57
            $rawProp    = $entityType->getAllProperties();
58
            $keyProp    = $entityType->getKeyProperties();
59
            $keyNames   = array_keys($keyProp);
60
            $nonRelProp = [];
61
            foreach ($rawProp as $prop) {
62
                $propName = $prop->getName();
63
                if (!in_array($propName, $keyNames) && !($prop->getResourceType() instanceof ResourceEntityType)) {
64
                    $nonRelProp[] = $propName;
65
                    $nonRelProp[] = strtolower($propName);
66
                }
67
            }
68
            self::$nonKeyPropertiesCache[$actualType] = $nonRelProp;
69
        }
70
71
        $nonRelProp = self::$nonKeyPropertiesCache[$actualType];
72
73
        // assemble data array
74
        $data = [];
75
        foreach ($payload->propertyContent as $propName => $propSpec) {
76
            if (in_array($propName, $nonRelProp) || in_array(strtolower($propName), $nonRelProp)) {
0 ignored issues
show
Bug introduced by
It seems like $propName can also be of type null; however, parameter $string of strtolower() does only seem to accept string, 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

76
            if (in_array($propName, $nonRelProp) || in_array(strtolower(/** @scrutinizer ignore-type */ $propName), $nonRelProp)) {
Loading history...
77
                /** @var string $rawVal */
78
                $rawVal = $propSpec->getValue();
79
                $value  = null;
80
                switch ($propSpec->getTypeName()) {
81
                    case 'Edm.Boolean':
82
                        $rawVal = trim(strtolower(strval($rawVal)));
83
                        $value  = 'true' == $rawVal;
84
                        break;
85
                    case 'Edm.DateTime':
86
                        $rawVal = trim(strval($rawVal));
87
                        if (1 < strlen($rawVal)) {
88
                            $valLen     = strlen($rawVal) - 6;
89
                            $offsetChek = $rawVal[$valLen];
90
                            $timezone   = new DateTimeZone('UTC');
91
                            if (18 < $valLen && ('-' == $offsetChek || '+' == $offsetChek)) {
92
                                $rawTz    = substr($rawVal, $valLen);
93
                                $rawVal   = substr($rawVal, 0, $valLen);
94
                                $rawBitz  = explode('.', $rawVal);
95
                                $rawVal   = $rawBitz[0];
96
                                $timezone = new DateTimeZone($rawTz);
97
                            }
98
                            $newValue = new DateTime($rawVal, $timezone);
99
                            // clamp assignable times to:
100
                            // after 1752, since OData DateTime epoch is apparently midnight 1 Jan 1753
101
                            // before 10000, since OData has a Y10K problem
102
                            if (1752 < $newValue->format('Y') && 10000 > $newValue->format('Y')) {
103
                                $value = $newValue;
104
                            }
105
                        }
106
                        break;
107
                    default:
108
                        $value = trim(strval($rawVal));
109
                        break;
110
                }
111
                $data[$propName] = $value;
112
            }
113
        }
114
115
        return $data;
116
    }
117
118
    /**
119
     * Reset properties cache.
120
     *
121
     * @return void
122
     */
123
    public function reset()
124
    {
125
        self::$nonKeyPropertiesCache = [];
126
    }
127
}
128