Completed
Pull Request — master (#17)
by Christian
02:51 queued 36s
created

StatementsApiClient::doStoreStatements()   D

Complexity

Conditions 14
Paths 32

Size

Total Lines 85
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 44.6064

Importance

Changes 0
Metric Value
dl 0
loc 85
ccs 18
cts 39
cp 0.4615
rs 4.9516
c 0
b 0
f 0
cc 14
eloc 50
nc 32
nop 4
crap 44.6064

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
/*
4
 * This file is part of the xAPI package.
5
 *
6
 * (c) Christian Flothmann <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Xabbuh\XApi\Client\Api;
13
14
use Http\Message\MultipartStream\MultipartStreamBuilder;
15
use Xabbuh\XApi\Client\Request\HandlerInterface;
16
use Xabbuh\XApi\Model\StatementId;
17
use Xabbuh\XApi\Serializer\ActorSerializerInterface;
18
use Xabbuh\XApi\Serializer\StatementResultSerializerInterface;
19
use Xabbuh\XApi\Serializer\StatementSerializerInterface;
20
use Xabbuh\XApi\Model\Actor;
21
use Xabbuh\XApi\Model\Statement;
22
use Xabbuh\XApi\Model\StatementResult;
23
use Xabbuh\XApi\Model\StatementsFilter;
24
25
/**
26
 * Client to access the statements API of an xAPI based learning record store.
27
 *
28
 * @author Christian Flothmann <[email protected]>
29
 */
30
final class StatementsApiClient implements StatementsApiClientInterface
31
{
32
    private $requestHandler;
33
    private $version;
34
    private $statementSerializer;
35
    private $statementResultSerializer;
36
    private $actorSerializer;
37
38
    /**
39
     * @param HandlerInterface                   $requestHandler            The HTTP request handler
40
     * @param string                             $version                   The xAPI version
41
     * @param StatementSerializerInterface       $statementSerializer       The statement serializer
42
     * @param StatementResultSerializerInterface $statementResultSerializer The statement result serializer
43
     * @param ActorSerializerInterface           $actorSerializer           The actor serializer
44
     */
45 17
    public function __construct(
46
        HandlerInterface $requestHandler,
47
        $version,
48
        StatementSerializerInterface $statementSerializer,
49
        StatementResultSerializerInterface $statementResultSerializer,
50
        ActorSerializerInterface $actorSerializer
51
    ) {
52 17
        $this->requestHandler = $requestHandler;
53 17
        $this->version = $version;
54 17
        $this->statementSerializer = $statementSerializer;
55 17
        $this->statementResultSerializer = $statementResultSerializer;
56 17
        $this->actorSerializer = $actorSerializer;
57 17
    }
58
59
    /**
60
     * {@inheritDoc}
61
     */
62 4
    public function storeStatement(Statement $statement)
63
    {
64 4
        if (null !== $statement->getId()) {
65 2
            return $this->doStoreStatements(
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->doStoreStatements...d()->getValue()), 204); of type array|Xabbuh\XApi\Model\Statement adds the type array to the return on line 65 which is incompatible with the return type declared by the interface Xabbuh\XApi\Client\Api\S...terface::storeStatement of type Xabbuh\XApi\Model\Statement.
Loading history...
66
                $statement,
67 2
                'put',
68 2
                array('statementId' => $statement->getId()->getValue()),
69 2
                204
70
            );
71
        } else {
72 2
            return $this->doStoreStatements($statement);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->doStoreStatements($statement); of type array|Xabbuh\XApi\Model\Statement adds the type array to the return on line 72 which is incompatible with the return type declared by the interface Xabbuh\XApi\Client\Api\S...terface::storeStatement of type Xabbuh\XApi\Model\Statement.
Loading history...
73
        }
74
    }
75
76
    /**
77
     * {@inheritDoc}
78
     */
79 4
    public function storeStatements(array $statements)
80
    {
81
        // check that only Statements without ids will be sent to the LRS
82 4
        foreach ($statements as $statement) {
83
            /** @var Statement $statement */
84
85 4
            $isStatement = is_object($statement) && $statement instanceof Statement;
86
87 4
            if (!$isStatement || null !== $statement->getId()) {
88 4
                throw new \InvalidArgumentException('API can only handle statements without ids');
89
            }
90
        }
91
92 1
        return $this->doStoreStatements($statements);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->doStoreStatements($statements); of type array|Xabbuh\XApi\Model\Statement adds the type Xabbuh\XApi\Model\Statement to the return on line 92 which is incompatible with the return type declared by the interface Xabbuh\XApi\Client\Api\S...erface::storeStatements of type Xabbuh\XApi\Model\Statement[].
Loading history...
93
    }
94
95
    /**
96
     * {@inheritDoc}
97
     */
98 1
    public function voidStatement(Statement $statement, Actor $actor)
99
    {
100 1
        return $this->storeStatement($statement->getVoidStatement($actor));
101
    }
102
103
    /**
104
     * {@inheritDoc}
105
     */
106 2
    public function getStatement(StatementId $statementId, $attachments = true)
107
    {
108 2
        return $this->doGetStatements('statements', array(
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->doGetStatements('...s ? 'true' : 'false')); of type Xabbuh\XApi\Model\Statem...i\Model\StatementResult adds the type Xabbuh\XApi\Model\StatementResult to the return on line 108 which is incompatible with the return type declared by the interface Xabbuh\XApi\Client\Api\S...Interface::getStatement of type Xabbuh\XApi\Model\Statement.
Loading history...
109 2
            'statementId' => $statementId->getValue(),
110 2
            'attachments' => $attachments ? 'true' : 'false',
111
        ));
112
    }
113
114
    /**
115
     * {@inheritDoc}
116
     */
117 2
    public function getVoidedStatement(StatementId $statementId, $attachments = true)
118
    {
119 2
        return $this->doGetStatements('statements', array(
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->doGetStatements('...s ? 'true' : 'false')); of type Xabbuh\XApi\Model\Statem...i\Model\StatementResult adds the type Xabbuh\XApi\Model\StatementResult to the return on line 119 which is incompatible with the return type declared by the interface Xabbuh\XApi\Client\Api\S...ace::getVoidedStatement of type Xabbuh\XApi\Model\Statement.
Loading history...
120 2
            'voidedStatementId' => $statementId->getValue(),
121 2
            'attachments' => $attachments ? 'true' : 'false',
122
        ));
123
    }
124
125
    /**
126
     * {@inheritDoc}
127
     */
128 4
    public function getStatements(StatementsFilter $filter = null)
129
    {
130 4
        $urlParameters = array();
131
132 4
        if (null !== $filter) {
133 3
            $urlParameters = $filter->getFilter();
134
        }
135
136
        // the Agent must be JSON encoded
137 4
        if (isset($urlParameters['agent'])) {
138 1
            $urlParameters['agent'] = $this->actorSerializer->serializeActor($urlParameters['agent']);
139
        }
140
141 4
        return $this->doGetStatements('statements', $urlParameters);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->doGetStatements('...ents', $urlParameters); of type Xabbuh\XApi\Model\Statem...i\Model\StatementResult adds the type Xabbuh\XApi\Model\Statement to the return on line 141 which is incompatible with the return type declared by the interface Xabbuh\XApi\Client\Api\S...nterface::getStatements of type Xabbuh\XApi\Model\StatementResult.
Loading history...
142
    }
143
144
    /**
145
     * {@inheritDoc}
146
     */
147 1
    public function getNextStatements(StatementResult $statementResult)
148
    {
149 1
        return $this->doGetStatements($statementResult->getMoreUrlPath()->getValue());
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->doGetStatements($...UrlPath()->getValue()); of type Xabbuh\XApi\Model\Statem...i\Model\StatementResult adds the type Xabbuh\XApi\Model\Statement to the return on line 149 which is incompatible with the return type declared by the interface Xabbuh\XApi\Client\Api\S...face::getNextStatements of type Xabbuh\XApi\Model\StatementResult.
Loading history...
150
    }
151
152
    /**
153
     * @param Statement|Statement[] $statements
154
     * @param string                $method
155
     * @param string[]              $parameters
156
     * @param int                   $validStatusCode
157
     *
158
     * @return Statement|Statement[] The created statement(s)
159
     */
160 5
    private function doStoreStatements($statements, $method = 'post', $parameters = array(), $validStatusCode = 200)
161
    {
162 5
        $attachments = array();
163
164 5
        if (is_array($statements)) {
165 1
            foreach ($statements as $statement) {
166 1
                if (null !== $statements->getAttachments()) {
0 ignored issues
show
Bug introduced by
The method getAttachments cannot be called on $statements (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
167
                    foreach ($statements->getAttachments() as $attachment) {
0 ignored issues
show
Bug introduced by
The method getAttachments cannot be called on $statements (of type array).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
168
                        if ($attachment->getContent()) {
169
                            $attachments[] = $attachment;
170
                        }
171
                    }
172
                }
173
            }
174
175
            $serializedStatements = $this->statementSerializer->serializeStatements($statements);
176
        } else {
177 4
            if (null !== $statements->getAttachments()) {
178
                foreach ($statements->getAttachments() as $attachment) {
179
                    if ($attachment->getContent()) {
0 ignored issues
show
Bug introduced by
The method getContent() does not exist on Xabbuh\XApi\Model\Attachment. Did you maybe mean getContentType()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
180
                        $attachments[] = $attachment;
181
                    }
182
                }
183
            }
184
185 4
            $serializedStatements = $this->statementSerializer->serializeStatement($statements);
186
        }
187
188 4
        $headers = array();
189
190 4
        if (!empty($attachments)) {
191
            $builder = new MultipartStreamBuilder();
192
            $builder->addResource('statement', $serializedStatements, array(
193
                'headers' => array(
194
                    'Content-Type' => 'application/json',
195
                ),
196
            ));
197
198
            foreach ($attachments as $index => $attachment) {
199
                $builder->addResource('attachment-'.$index, $attachment->getContent(), array(
200
                    'headers' => array(
201
                        'Content-Type' => $attachment->getContentType(),
202
                        'Content-Transfer-Encoding' => 'binary',
203
                        'X-Experience-API-Hash' => $attachment->getSha2(),
204
                    ),
205
                ));
206
            }
207
208
            $headers = array(
209
                'Content-Type' => 'multipart/mixed; boundary='.$builder->getBoundary(),
210
            );
211
            $body = $builder->build();
212
        } else {
213 4
            $body = $serializedStatements;
214
        }
215
216 4
        $request = $this->requestHandler->createRequest(
217
            $method,
218 4
            'statements',
219
            $parameters,
220
            $body,
221
            $headers
222
        );
223 4
        $response = $this->requestHandler->executeRequest($request, array($validStatusCode));
224 4
        $statementIds = json_decode((string) $response->getBody());
225
226 4
        if (is_array($statements)) {
227
            /** @var Statement[] $statements */
228
            $createdStatements = array();
229
230
            foreach ($statements as $index => $statement) {
231
                $createdStatements[] = $statement->withId(StatementId::fromString($statementIds[$index]));
232
            }
233
234
            return $createdStatements;
235
        } else {
236
            /** @var Statement $statements */
237
238 4
            if (200 === $validStatusCode) {
239 2
                return $statements->withId(StatementId::fromString($statementIds[0]));
240
            } else {
241 2
                return $statements;
242
            }
243
        }
244
    }
245
246
    /**
247
     * Fetch one or more Statements.
248
     *
249
     * @param string $url           URL to request
250
     * @param array  $urlParameters URL parameters
251
     *
252
     * @return Statement|StatementResult
253
     */
254 9
    private function doGetStatements($url, array $urlParameters = array())
255
    {
256 9
        $request = $this->requestHandler->createRequest('get', $url, $urlParameters);
257 5
        $response = $this->requestHandler->executeRequest($request, array(200));
258
259 5
        if (isset($urlParameters['statementId']) || isset($urlParameters['voidedStatementId'])) {
260
            return $this->statementSerializer->deserializeStatement((string) $response->getBody());
261
        } else {
262 5
            return $this->statementResultSerializer->deserializeStatementResult((string) $response->getBody());
263
        }
264
    }
265
}
266