Passed
Push — ref ( 45b89b )
by Asmir
02:50
created

ArgumentsReader::readArguments()   B

Complexity

Conditions 10
Paths 10

Size

Total Lines 62
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 37
c 1
b 0
f 0
dl 0
loc 62
rs 7.6666
cc 10
nc 10
nop 2

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
namespace GoetasWebservices\SoapServices\Metadata\Arguments;
4
5
use Doctrine\Instantiator\Instantiator;
6
use GoetasWebservices\SoapServices\Metadata\Arguments\Headers\Handler\HeaderHandler;
7
use GoetasWebservices\SoapServices\Metadata\Arguments\Headers\Handler\HeaderPlaceholder;
8
use GoetasWebservices\SoapServices\Metadata\Arguments\Headers\Header;
9
use GoetasWebservices\SoapServices\Metadata\SerializerUtils;
10
use GoetasWebservices\SoapServices\SoapServer\Serializer\Handler\HeaderHandlerInterface;
0 ignored issues
show
Bug introduced by
The type GoetasWebservices\SoapSe...\HeaderHandlerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use JMS\Serializer\Accessor\DefaultAccessorStrategy;
12
use JMS\Serializer\DeserializationContext;
13
use JMS\Serializer\Metadata\PropertyMetadata;
14
use JMS\Serializer\Serializer;
15
16
class ArgumentsReader implements ArgumentsReaderInterface
17
{
18
    /**
19
     * @var Serializer
20
     */
21
    private $serializer;
22
    /**
23
     * @var HeaderHandler
24
     */
25
    private $headerHandler;
0 ignored issues
show
introduced by
The private property $headerHandler is not used, and could be removed.
Loading history...
26
27
    public function __construct(Serializer $serializer)
28
    {
29
        $this->serializer = $serializer;
30
    }
31
32
    /**
33
     * @param array $args
34
     * @param array $message
35
     * @return null|object
36
     */
37
    public function readArguments(array $args, array $message)
38
    {
39
        $envelope = array_filter($args, function ($item) use ($message) {
40
            return $item instanceof $message['message_fqcn'];
41
        });
42
        if ($envelope) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $envelope of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
43
            return reset($envelope);
44
        }
45
46
        $instantiator = new Instantiator();
47
        $envelope = $instantiator->instantiate($message['message_fqcn']);
48
49
        if (!count($message['parts'])) {
50
            return $envelope;
51
        }
52
53
        $args = $this->handleHeaders($args, $message, $envelope);
54
        if ($args[0] instanceof $message['part_fqcn']) {
55
            $envelope->setBody($args[0]);
56
            return $envelope;
57
        }
58
59
        $body = $instantiator->instantiate($message['part_fqcn']);
60
        $envelope->setBody($body);
61
62
        $factory = SerializerUtils::getMetadataFactory($this->serializer);
63
64
        $classMetadata = $factory->getMetadataForClass($message['part_fqcn']);
65
66
        if (count($message['parts']) > 1) {
67
68
            if (count($message['parts']) !== count($args)) {
69
                throw new \Exception("Expected to have exactly " . count($message['parts']) . " arguments, supplied " . count($args));
70
            }
71
72
            foreach ($message['parts'] as $paramName => $elementName) {
73
                $propertyMetadata = $classMetadata->propertyMetadata[$paramName];
0 ignored issues
show
Bug introduced by
The property propertyMetadata does not seem to exist on Metadata\ClassHierarchyMetadata.
Loading history...
74
                $this->setValue($body, array_shift($args), $propertyMetadata);
75
            }
76
            return $envelope;
77
        }
78
79
        $propertyName = key($message['parts']);
80
        $propertyMetadata = $classMetadata->propertyMetadata[$propertyName];
81
82
        if ($args[0] instanceof $propertyMetadata->type['name']) {
83
            $this->setValue($body, reset($args), $propertyMetadata);
84
            return $envelope;
85
        }
86
87
        $instance2 = $instantiator->instantiate($propertyMetadata->type['name']);
88
        $classMetadata2 = $factory->getMetadataForClass($propertyMetadata->type['name']);
89
        $this->setValue($body, $instance2, $propertyMetadata);
90
91
        foreach ($classMetadata2->propertyMetadata as $propertyMetadata2) {
92
            if (!count($args)) {
93
                throw new \Exception("Not enough arguments provided. Can't find a parameter to set " . $propertyMetadata2->name);
94
            }
95
            $value = array_shift($args);
96
            $this->setValue($instance2, $value, $propertyMetadata2);
97
        }
98
        return $envelope;
99
    }
100
101
    /**
102
     * @param array $args
103
     * @param array $message
104
     * @param $envelope
105
     * @return array
106
     */
107
    private function handleHeaders(array $args, array $message, $envelope)
108
    {
109
        $headers = array_filter($args, function ($item) use ($message) {
110
            return $item instanceof $message['headers_fqcn'];
111
        });
112
        if ($headers) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $headers of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
113
            $envelope->setHeader(reset($headers));
114
        } else {
115
116
            $headers = array_filter($args, function ($item) {
117
                return $item instanceof Header;
118
            });
119
            if (count($headers)) {
120
121
                $factory = SerializerUtils::getMetadataFactory($this->serializer);
122
                $classMetadata = $factory->getMetadataForClass($message['message_fqcn']);
123
                $propertyMetadata = $classMetadata->propertyMetadata['header'];
0 ignored issues
show
Bug introduced by
The property propertyMetadata does not seem to exist on Metadata\ClassHierarchyMetadata.
Loading history...
124
125
                $instantiator = new Instantiator();
126
                $header = $instantiator->instantiate($propertyMetadata->type['name']);
127
                foreach ($headers as $headerInfo) {
128
                    $header->addHeader($headerInfo);
129
                }
130
131
                $envelope->setHeader($header);
132
            }
133
        }
134
135
        $args = array_filter($args, function ($item) use ($message) {
136
            return !($item instanceof Header) && !($item instanceof $message['headers_fqcn']);
137
        });
138
        return $args;
139
    }
140
141
142
    private function setValue($target, $value, PropertyMetadata $propertyMetadata): void
143
    {
144
        $context = DeserializationContext::create();
145
        $accessor = new DefaultAccessorStrategy();
146
147
        $accessor->setValue($target, $value, $propertyMetadata, $context);
148
    }
149
}
150