Completed
Push — master ( 00c305...784882 )
by Nate
03:32
created

BodyHandler::createContext()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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