Completed
Pull Request — master (#14)
by Artem
06:19
created

ResponseProcessor::processResponse()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 33
rs 9.0808
c 0
b 0
f 0
cc 5
nc 5
nop 2
1
<?php
2
/*
3
 * This file is part of the FreshCentrifugoBundle.
4
 *
5
 * (c) Artem Henvald <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
declare(strict_types=1);
12
13
namespace Fresh\CentrifugoBundle\Service;
14
15
use Fresh\CentrifugoBundle\Exception\CentrifugoErrorException;
16
use Fresh\CentrifugoBundle\Exception\CentrifugoException;
17
use Fresh\CentrifugoBundle\Exception\LogicException;
18
use Fresh\CentrifugoBundle\Logger\CommandHistoryLogger;
19
use Fresh\CentrifugoBundle\Model\BatchRequest;
20
use Fresh\CentrifugoBundle\Model\CommandInterface;
21
use Fresh\CentrifugoBundle\Model\ResultableCommandInterface;
22
use Symfony\Component\HttpKernel\Profiler\Profiler;
23
use Symfony\Contracts\HttpClient\ResponseInterface;
24
25
/**
26
 * ResponseProcessor.
27
 *
28
 * @author Artem Henvald <[email protected]>
29
 */
30
class ResponseProcessor
31
{
32
    private CentrifugoChecker $centrifugoChecker;
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_STRING, expecting T_FUNCTION or T_CONST
Loading history...
33
    private bool $profilerEnabled;
34
    private CommandHistoryLogger $commandHistoryLogger;
35
    private array $centrifugoError = [];
36
37
    /**
38
     * @param CentrifugoChecker    $centrifugoChecker
39
     * @param CommandHistoryLogger $commandHistoryLogger
40
     * @param Profiler|null        $profiler
41
     */
42
    public function __construct(CentrifugoChecker $centrifugoChecker, CommandHistoryLogger $commandHistoryLogger, ?Profiler $profiler)
43
    {
44
        $this->centrifugoChecker = $centrifugoChecker;
45
        $this->profilerEnabled = $profiler instanceof Profiler;
46
        $this->commandHistoryLogger = $commandHistoryLogger;
47
    }
48
49
    /**
50
     * @param CommandInterface  $command
51
     * @param ResponseInterface $response
52
     *
53
     * @throws LogicException
54
     * @throws CentrifugoErrorException
55
     *
56
     * @return array|null
57
     */
58
    public function processResponse(CommandInterface $command, ResponseInterface $response): ?array
59
    {
60
        $this->centrifugoChecker->assertValidResponseStatusCode($response);
61
        $this->centrifugoChecker->assertValidResponseHeaders($response);
62
        $this->centrifugoChecker->assertValidResponseContentType($response);
63
64
        $this->centrifugoError = [];
65
66
        $content = $response->getContent();
67
68
        if ($command instanceof BatchRequest) {
69
            $contents = \explode("\n", \rtrim($content, "\n"));
70
            $result = [];
71
72
            if (\count($contents) !== $command->getNumberOfCommands()) {
73
                throw new LogicException('Number of commands doesn\'t match number of responses');
74
            }
75
76
            $i = 0;
77
            foreach ($command->getCommands() as $innerCommand) {
78
                $result[] = $this->decodeAndProcessResponseResult($innerCommand, $contents[$i]);
79
                ++$i;
80
            }
81
        } else {
82
            $result = $this->decodeAndProcessResponseResult($command, $content);
83
        }
84
85
        if (isset($this->centrifugoError['message'], $this->centrifugoError['code'])) {
86
            throw new CentrifugoErrorException($this->centrifugoError['message'], $this->centrifugoError['code']);
87
        }
88
89
        return $result;
90
    }
91
92
    /**
93
     * @param CommandInterface $command
94
     * @param string           $content
95
     *
96
     * @throws CentrifugoException
97
     *
98
     * @return array|null
99
     */
100
    private function decodeAndProcessResponseResult(CommandInterface $command, string $content): ?array
101
    {
102
        try {
103
            $data = \json_decode($content, true, 512, \JSON_THROW_ON_ERROR);
104
        } catch (\Exception $e) {
105
            throw new CentrifugoException('Centrifugo response payload is not a valid JSON');
106
        }
107
108
        $successfulCommand = true;
109
        $result = null;
110
111
        if (isset($data['error'])) {
112
            if (empty($this->centrifugoError)) {
113
                $this->centrifugoError = [
114
                    'message' => $data['error']['message'],
115
                    'code' => $data['error']['code'],
116
                ];
117
            }
118
119
            $result = $data;
120
            $successfulCommand = false;
121
        } elseif ($command instanceof ResultableCommandInterface) {
122
            $result = $data['result'];
123
        }
124
125
        if ($this->profilerEnabled) {
126
            $this->commandHistoryLogger->logCommand($command, $successfulCommand, $result);
127
        }
128
129
        return $result;
130
    }
131
}
132