Completed
Push — master ( 2a804a...3f4c76 )
by Asmir
11s
created

ArgumentsReader::setPropertyValue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
crap 1
1
<?php
2
3
namespace GoetasWebservices\SoapServices\SoapClient\Arguments;
4
5
use Doctrine\Instantiator\Instantiator;
6
use GoetasWebservices\SoapServices\SoapClient\Arguments\Headers\Handler\HeaderHandler;
7
use GoetasWebservices\SoapServices\SoapClient\Arguments\Headers\Handler\HeaderPlaceholder;
8
use GoetasWebservices\SoapServices\SoapClient\Arguments\Headers\Header;
9
use GoetasWebservices\SoapServices\SoapClient\SerializerUtils;
10
use JMS\Serializer\Serializer;
11
use Metadata\MetadataFactoryInterface;
12
use Metadata\PropertyMetadata;
13
14
class ArgumentsReader implements ArgumentsReaderInterface
15
{
16
    /**
17
     * @var Serializer
18
     */
19
    private $serializer;
20
    /**
21
     * @var HeaderHandler
22
     */
23
    private $headerHandler;
24
25 36
    public function __construct(Serializer $serializer, HeaderHandler $headerHandler)
26
    {
27 36
        $this->serializer = $serializer;
28 36
        $this->headerHandler = $headerHandler;
29 36
    }
30
31 30
    private function setPropertyValue($propertyMetadata, $object, $value) {
32 30
        $reflectionProperty = new \ReflectionProperty($propertyMetadata->class, $propertyMetadata->name);
33 30
        $reflectionProperty->setAccessible(true);
34 30
        $reflectionProperty->setValue($object, $value);
35 30
    }
36
37
    /**
38
     * @param array $args
39
     * @param array $input
40
     * @return null|object
41
     */
42 34
    public function readArguments(array $args, array $input)
43
    {
44
45
        $envelope = array_filter($args, function ($item) use ($input) {
46 34
            return $item instanceof $input['message_fqcn'];
47 34
        });
48 34
        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...
49
            return reset($envelope);
50
        }
51
52 34
        $instantiator = new Instantiator();
53 34
        $envelope = $instantiator->instantiate($input['message_fqcn']);
54
55 34
        $args = $this->handleHeaders($args, $input, $envelope);
56
57 34
        if (!count($input['parts'])) {
58 4
            return $envelope;
59
        }
60
61 30
        $body = $instantiator->instantiate($input['part_fqcn']);
62 30
        $envelope->setBody($body);
63 30
        $factory = SerializerUtils::getMetadataFactory($this->serializer);
64 30
        $classMetadata = $factory->getMetadataForClass($input['part_fqcn']);
65
66 30
        if (count($input['parts']) > 1) {
67
68 2
            if (count($input['parts']) !== count($args)) {
69
                throw new \Exception("Expected to have exactly " . count($input['parts']) . " arguments, supplied " . count($args));
70
            }
71
72 2
            foreach ($input['parts'] as $paramName => $elementName) {
73 2
                $propertyMetadata = $classMetadata->propertyMetadata[$paramName];
74 2
                $this->setPropertyValue($propertyMetadata, $body, array_shift($args));
75 2
            }
76 2
            return $envelope;
77
        }
78
79 28
        $propertyName = key($input['parts']);
80 28
        $propertyMetadata = $classMetadata->propertyMetadata[$propertyName];
81 28
        if (isset($args[0]) && $args[0] instanceof $propertyMetadata->type['name']) {
82 2
            $this->setPropertyValue($propertyMetadata, $body, reset($args));
83 2
            return $envelope;
84
        }
85
86 26
        $instance2 = $instantiator->instantiate($propertyMetadata->type['name']);
87 26
        $classMetadata2 = $factory->getMetadataForClass($propertyMetadata->type['name']);
88 26
        $this->setPropertyValue($propertyMetadata, $body, $instance2);
89
90 26
        foreach ($classMetadata2->propertyMetadata as $propertyMetadata2) {
91 26
            if (!count($args)) {
92
                throw new \Exception("Not enough arguments provided. Can't find a parameter to set " . $propertyMetadata2->name);
93
            }
94 26
            $value = array_shift($args);
95 26
            $this->setPropertyValue($propertyMetadata2, $instance2, $value);
96 26
        }
97 26
        return $envelope;
98
    }
99
100
    /**
101
     * @param array $args
102
     * @param array $input
103
     * @param $envelope
104
     * @return array
105
     */
106 34
    private function handleHeaders(array $args, array $input, $envelope)
107
    {
108
        $headers = array_filter($args, function ($item) use ($input) {
109 34
            return $item instanceof $input['headers_fqcn'];
110 34
        });
111 34
        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...
112
            $envelope->setHeader(reset($headers));
113
        } else {
114
115
            $headers = array_filter($args, function ($item) {
116 34
                return $item instanceof Header;
117 34
            });
118 34
            if (count($headers)) {
119 2
                $headerPlaceholder = new HeaderPlaceholder();
120 2
                foreach ($headers as $headerInfo) {
121 2
                    $this->headerHandler->addHeaderData($headerPlaceholder, $headerInfo);
122 2
                }
123 2
                $envelope->setHeader($headerPlaceholder);
124 2
            }
125
        }
126
127 34
        $args = array_filter($args, function ($item) use ($input) {
128 34
            return !($item instanceof Header) && !($item instanceof $input['headers_fqcn']);
129 34
        });
130 34
        return $args;
131
    }
132
}
133