Completed
Push — master ( cd52e5...2b62de )
by Artem
01:26
created

decodeAndProcessResponseResult()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

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