| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | /* | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  |  * This file is part of the NNTP library. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  |  * (c) Robin van der Vleuten <[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 Rvdv\Nntp\Connection; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | use Rvdv\Nntp\Command\CommandInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | use Rvdv\Nntp\Exception\InvalidArgumentException; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | use Rvdv\Nntp\Exception\RuntimeException; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | use Rvdv\Nntp\Exception\UnknownHandlerException; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | use Rvdv\Nntp\Response\MultiLineResponse; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | use Rvdv\Nntp\Response\Response; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  | use Rvdv\Nntp\Response\ResponseInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | use Rvdv\Nntp\Socket\Socket; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | use Rvdv\Nntp\Socket\SocketInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |  * @author Robin van der Vleuten <[email protected]> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  | class Connection implements ConnectionInterface | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |     const BUFFER_SIZE = 1024; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |      * @var string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  |     private $host; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  |      * @var int | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |     private $port; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |      * @var bool | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |     private $secure; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |      * @var SocketInterface | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |     private $socket; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |      * Constructor. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |      * @param string          $host   the host of the NNTP server | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |      * @param int             $port   the port of the NNTP server | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |      * @param bool            $secure a bool indicating if a secure connection should be established | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |      * @param SocketInterface $socket an optional socket wrapper instance | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 | 2 |  |     public function __construct($host, $port, $secure = false, SocketInterface $socket = null) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 | 2 |  |         $this->host = $host; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 | 2 |  |         $this->port = $port; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 | 2 |  |         $this->secure = $secure; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 | 2 |  |         $this->socket = $socket ?: new Socket(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 | 2 |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |      * {@inheritdoc} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 | 2 |  |     public function connect() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 | 2 |  |         $this->socket->connect(sprintf('tcp://%s:%d', $this->host, $this->port)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 | 1 |  |         if ($this->secure) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |             $this->socket->enableCrypto(true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 | 1 |  |         return $this->getResponse(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |      * {@inheritdoc} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |     public function disconnect() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |         $this->socket->disconnect(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |      * {@inheritdoc} | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |     public function sendCommand(CommandInterface $command) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |         $commandString = $command(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |         // NNTP/RFC977 only allows command up to 512 (-2 \r\n) chars. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |         if (!strlen($commandString) > 510) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |             throw new InvalidArgumentException('Failed to write to socket: command exceeded 510 characters'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |         if (strlen($commandString."\r\n") !== $this->socket->write($commandString."\r\n")) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |             throw new RuntimeException('Failed to write to socket'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |         $response = $this->getResponse(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |         if ($command->isMultiLine() && ($response->getStatusCode() >= 200 && $response->getStatusCode() <= 399)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |             $response = $command->isCompressed() ? $this->getCompressedResponse($response) : $this->getMultiLineResponse($response); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |         return $this->callCommandHandlerForResponse($command, $response); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |     public function sendArticle(CommandInterface $command) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |         $commandString = $command->execute(); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |         if (strlen($commandString."\r\n.\r\n") !== $this->socket->write($commandString."\r\n.\r\n")) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |             throw new RuntimeException('Failed to write to socket'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |         $response = $this->getResponse(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |         return $this->callCommandHandlerForResponse($command, $response); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 | 1 |  |     private function getResponse() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 | 1 |  |         $buffer = ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 | 1 |  |         while (!$this->socket->eof()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 | 1 |  |             $buffer .= $this->socket->gets(self::BUFFER_SIZE); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 | 1 |  |             if ("\r\n" === substr($buffer, -2)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 | 1 |  |                 break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |             if ($buffer === false) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |                 $this->disconnect(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |                 throw new RuntimeException('Incorrect data received from buffer'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 | 1 |  |         return Response::createFromString($buffer); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |     private function getMultiLineResponse(Response $response) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |         $lines = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  |         while (!$this->socket->eof()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  |             $line = $this->socket->gets(self::BUFFER_SIZE); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 |  |  |             if (substr($line, -2) !== "\r\n" || strlen($line) < 2) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 |  |  |                 continue; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 |  |  |             // Remove CR LF from the end of the line. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  |             $line = substr($line, 0, -2); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 |  |  |             // Check if the line terminates the text response. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  |             if ($line === '.') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  |                 return new MultiLineResponse($response, array_filter($lines)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  |             // If 1st char is '.' it's doubled (NNTP/RFC977 2.4.1). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  |             if (substr($line, 0, 2) === '..') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 |  |  |                 $line = substr($line, 1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 |  |  |             // Add the line to the array of lines. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 |  |  |             $lines[] = $line; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 |  |  |     private function getCompressedResponse(Response $response) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 176 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 177 |  |  |         // Determine encoding by fetching first line. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 |  |  |         $line = $this->socket->gets(self::BUFFER_SIZE); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 179 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 180 |  |  |         if (substr($line, 0, 7) == '=ybegin') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 181 |  |  |             $this->disconnect(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 182 |  |  |             throw new RuntimeException('yEnc encoded overviews are not currently supported.'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 183 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 184 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 185 |  |  |         $uncompressed = ''; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 186 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 187 |  |  |         while (!$this->socket->eof()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 188 |  |  |             $buffer = $this->socket->gets(self::BUFFER_SIZE); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 189 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 190 |  |  |             if (strlen($buffer) === 0) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 191 |  |  |                 $uncompressed = @gzuncompress($line); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 192 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 193 |  |  |                 if ($uncompressed !== false) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 194 |  |  |                     break; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 195 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 196 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 197 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 198 |  |  |             if ($buffer === false) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 199 |  |  |                 $this->disconnect(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 200 |  |  |                 throw new RuntimeException('Incorrect data received from buffer'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 201 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 202 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 203 |  |  |             $line .= $buffer; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 204 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 205 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 206 |  |  |         $lines = explode("\r\n", trim($uncompressed)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 207 |  |  |         if (end($lines) === '.') { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 208 |  |  |             array_pop($lines); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 209 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 210 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 211 |  |  |         $lines = array_filter($lines); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 212 |  |  |         $lines = \SplFixedArray::fromArray($lines); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 213 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 214 |  |  |         return new MultiLineResponse($response, $lines); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 215 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 216 |  |  |  | 
            
                                                        
            
                                    
            
            
                | 217 |  |  |     private function callCommandHandlerForResponse(CommandInterface $command, ResponseInterface $response) | 
            
                                                        
            
                                    
            
            
                | 218 |  |  |     { | 
            
                                                        
            
                                    
            
            
                | 219 |  |  |         if (in_array($response->getStatusCode(), [Response::$codes['CommandUnknown'], Response::$codes['CommandUnavailable']])) { | 
            
                                                        
            
                                    
            
            
                | 220 |  |  |             throw new RuntimeException('Sent command is either unknown or unavailable on server'); | 
            
                                                        
            
                                    
            
            
                | 221 |  |  |         } | 
            
                                                        
            
                                    
            
            
                | 222 |  |  |  | 
            
                                                        
            
                                    
            
            
                | 223 |  |  |         // Check if we received a response code that we're aware of. | 
            
                                                        
            
                                    
            
            
                | 224 |  |  |         if (($responseName = array_search($response->getStatusCode(), Response::$codes, true)) === false) { | 
            
                                                        
            
                                    
            
            
                | 225 |  |  |             throw new RuntimeException(sprintf( | 
            
                                                        
            
                                    
            
            
                | 226 |  |  |                 'Unexpected response received: [%d] %s', | 
            
                                                        
            
                                    
            
            
                | 227 |  |  |                 $response->getStatusCode(), | 
            
                                                        
            
                                    
            
            
                | 228 |  |  |                 $response->getMessage() | 
            
                                                        
            
                                    
            
            
                | 229 |  |  |             )); | 
            
                                                        
            
                                    
            
            
                | 230 |  |  |         } | 
            
                                                        
            
                                    
            
            
                | 231 |  |  |  | 
            
                                                        
            
                                    
            
            
                | 232 |  |  |         $responseHandlerMethod = 'on'.$responseName; | 
            
                                                        
            
                                    
            
            
                | 233 |  |  |  | 
            
                                                        
            
                                    
            
            
                | 234 |  |  |         if (!is_callable([$command, $responseHandlerMethod])) { | 
            
                                                        
            
                                    
            
            
                | 235 |  |  |             throw new UnknownHandlerException(sprintf('Response handler (%s) is not a callable method on given command object', $responseHandlerMethod)); | 
            
                                                        
            
                                    
            
            
                | 236 |  |  |         } | 
            
                                                        
            
                                    
            
            
                | 237 |  |  |  | 
            
                                                        
            
                                    
            
            
                | 238 |  |  |         return call_user_func([$command, $responseHandlerMethod], $response); | 
            
                                                        
            
                                    
            
            
                | 239 |  |  |     } | 
            
                                                        
            
                                    
            
            
                | 240 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 241 |  |  |  | 
            
                        
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.