Completed
Push — master ( 2ac042...4e5e3b )
by Nate
02:40
created

BodyHandler::doCreateBody()   C

Complexity

Conditions 7
Paths 5

Size

Total Lines 42
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 42
rs 6.7272
cc 7
eloc 23
nc 5
nop 1
1
<?php
2
/*
3
 * Copyright (c) 2015 Nate Brunette.
4
 * Distributed under the MIT License (http://opensource.org/licenses/MIT)
5
 */
6
7
namespace Tebru\Retrofit\Generation\Handler;
8
9
use LogicException;
10
use Tebru\Retrofit\Generation\Handler;
11
use Tebru\Retrofit\Generation\HandlerContext;
12
use Tebru\Retrofit\Generation\Manipulator\QueryManipulator;
13
14
/**
15
 * Class BodyHandler
16
 *
17
 * @author Nate Brunette <[email protected]>
18
 */
19
class BodyHandler implements Handler
20
{
21
    /**
22
     * Create body
23
     *
24
     * @param HandlerContext $context
25
     * @return null
26
     * @throws LogicException
27
     */
28
    public function __invoke(HandlerContext $context)
29
    {
30
        if (!$context->annotations()->hasBody()) {
31
            $context->body()->add('$body = null;');
32
33
            return null;
34
        }
35
36
        // if body is optional and 'empty' it should be null
37
        if ($context->annotations()->isBodyOptional()) {
38
            $context->body()->add('if (empty(%s)) { $body = null; } else {', $context->annotations()->getBody());
39
        }
40
41
        $this->doCreateBody($context);
42
43
        if ($context->annotations()->isBodyOptional()) {
44
            $context->body()->add('}');
45
        }
46
    }
47
48
    /**
49
     * Create the body
50
     *
51
     * @param HandlerContext $context
52
     * @return null
53
     * @throws LogicException
54
     */
55
    private function doCreateBody(HandlerContext $context)
56
    {
57
        $body = $context->annotations()->getBody();
58
59
        // check if body is a string, set variable if it doesn't already equal '$body'
60
        if (!$context->annotations()->isBodyArray() && !$context->annotations()->isBodyObject() && null === $context->annotations()->getBodyParts()) {
61
            if ('$body' !== $body) {
62
                $context->body()->add('$body = %s;', $body);
63
            }
64
65
            return null;
66
        }
67
68
        // if we're json encoding, we don't need the body as an array first
69
        if ($context->annotations()->isJsonEncoded()) {
70
            $this->createBodyJson($context);
71
72
            return null;
73
        }
74
75
        // otherwise, we do need to convert the body to an array
76
        $this->createBodyArray($context);
77
78
        if ($context->annotations()->isFormUrlEncoded()) {
79
            $context->body()->add('$bodyArray = \Tebru\Retrofit\Generation\Manipulator\QueryManipulator::boolToString($bodyArray);');
80
            $context->body()->add('$body = http_build_query($bodyArray);');
81
82
            return null;
83
        }
84
85
        // body is multipart
86
        $context->body()->add('$bodyParts = [];');
87
        $context->body()->add('foreach ($bodyArray as $key => $value) {');
88
        $context->body()->add('$file = null;');
89
        $context->body()->add('if (is_resource($value)) { $file = $value; }');
90
        $context->body()->add('if (is_string($value)) { $file = fopen($value, "r"); }');
91
        $context->body()->add('if (!is_resource($file)) { throw new \LogicException("Expected resource or file path"); }');
92
        $context->body()->add('$bodyParts[] = ["name" => $key, "contents" => $file];');
93
        $context->body()->add('}');
94
95
        $context->body()->add('$body = new \GuzzleHttp\Psr7\MultipartStream($bodyParts, "%s");', $context->annotations()->getMultipartBoundary());
96
    }
97
98
    /**
99
     * Create json body logic
100
     *
101
     * @param HandlerContext $context
102
     * @return null
103
     * @throws LogicException
104
     */
105 View Code Duplication
    private function createBodyJson(HandlerContext $context)
106
    {
107
        $body = $context->annotations()->getBody();
108
109
        // json encode arrays
110
        if ($context->annotations()->isBodyArray()) {
111
            $context->body()->add('$body = json_encode(%s);', $body);
112
113
            return null;
114
        }
115
116
        // if parts exist, json encode the parts
117
        if (null !== $context->annotations()->getBodyParts()) {
118
            $context->body()->add('$body = json_encode(%s);', $context->printer()->printArray($context->annotations()->getBodyParts()));
119
120
            return null;
121
        }
122
123
        // if it's an object, serialize it unless it implements \JsonSerializable
124
        if ($context->annotations()->isBodyJsonSerializable()) {
125
            $context->body()->add('$body = json_encode(%s);', $body);
126
127
            return null;
128
        }
129
130
        $this->createContext($context, '$bodySerializationContext');
131
        $context->body()->add('$body = $this->serializer->serialize(%s, "json", $bodySerializationContext);', $body);
132
    }
133
134
    /**
135
     * Create body as array first
136
     *
137
     * @param HandlerContext $context
138
     * @return null
139
     * @throws LogicException
140
     */
141 View Code Duplication
    private function createBodyArray(HandlerContext $context)
142
    {
143
        $body = $context->annotations()->getBody();
144
145
        // if it's already an array, set to variable
146
        if ($context->annotations()->isBodyArray()) {
147
            $context->body()->add('$bodyArray = %s;', $body);
148
149
            return null;
150
        }
151
152
        // if parts exist, set to variable
153
        if (null !== $context->annotations()->getBodyParts()) {
154
            $context->body()->add('$bodyArray = %s;', $context->printer()->printArray($context->annotations()->getBodyParts()));
155
156
            return null;
157
        }
158
159
        // if it implements \JsonSerializable, call jsonSerialize() to get array
160
        if ($context->annotations()->isBodyJsonSerializable()) {
161
            $context->body()->add('$bodyArray = %s->jsonSerialize();', $body);
162
163
            return;
164
        }
165
166
        // otherwise, convert to array
167
        $this->createContext($context, '$bodySerializationContext');
168
        $context->body()->add('$bodyArray = $this->serializer->toArray(%s, $bodySerializationContext);', $body);
169
    }
170
171
    /**
172
     * Create serialization context
173
     *
174
     * @param HandlerContext $context
175
     * @param string $contextVar
176
     * @return null
177
     */
178
    private function createContext(HandlerContext $context, $contextVar)
179
    {
180
        $serializationContext = $context->annotations()->getSerializationContext();
181
182
        $context->body()->add('%s = \JMS\Serializer\SerializationContext::create();', $contextVar);
183
184
        if (0 === count($serializationContext)) {
185
            return null;
186
        }
187
188
        if (!empty($serializationContext['groups'])) {
189
            $context->body()->add('%s->setGroups(%s);', $contextVar, $context->printer()->printArray($serializationContext['groups']));
190
        }
191
192
        if (!empty($serializationContext['version'])) {
193
            $context->body()->add('%s->setVersion(%d);', $contextVar, (int) $serializationContext['version']);
194
        }
195
196
        if (!empty($serializationContext['serializeNull'])) {
197
            $serializeNull = QueryManipulator::boolToString([(bool) $serializationContext['serializeNull']])[0];
198
            $context->body()->add('%s->setSerializeNull(%s);', $contextVar, $serializeNull);
199
        }
200
201
        if (!empty($serializationContext['enableMaxDepthChecks'])) {
202
            $context->body()->add('%s->enableMaxDepthChecks();', $contextVar);
203
        }
204
205
        if (!empty($serializationContext['attributes'])) {
206
            foreach ($serializationContext['attributes'] as $key => $value) {
207
                $context->body()->add('%s->setAttribute("%s", "%s");', $contextVar, $key, $value);
208
            }
209
        }
210
    }
211
}
212