Issues (3)

src/TS3Client.php (1 issue)

1
<?php
2
/**
3
 * Class TS3Client
4
 *
5
 * @created      02.10.2016
6
 * @author       Smiley <[email protected]>
7
 * @copyright    2016 Smiley
8
 * @license      MIT
9
 */
10
11
namespace chillerlan\Teamspeak;
12
13
use chillerlan\Settings\SettingsContainerInterface;
14
use Psr\Log\{LoggerAwareInterface, LoggerAwareTrait, LoggerInterface, NullLogger};
15
use ErrorException, Throwable;
16
17
use function fclose, fsockopen, fwrite, is_resource, restore_error_handler,
18
	set_error_handler, stream_get_contents, stream_set_timeout, trim;
19
20
class TS3Client implements LoggerAwareInterface{
21
	use LoggerAwareTrait;
22
23
	/**
24
	 * @var \chillerlan\Teamspeak\TS3Config
25
	 */
26
	protected SettingsContainerInterface $config;
27
28
	/**
29
	 * @var resource|null
30
	 */
31
	protected $socket;
32
33
	/**
34
	 * TS3Client constructor.
35
	 *
36
	 * @param \chillerlan\Settings\SettingsContainerInterface $config
37
	 * @param \Psr\Log\LoggerInterface|null                   $logger
38
	 */
39
	public function __construct(SettingsContainerInterface $config, LoggerInterface $logger = null){
40
		$this->config = $config;
0 ignored issues
show
Documentation Bug introduced by
$config is of type chillerlan\Settings\SettingsContainerInterface, but the property $config was declared to be of type chillerlan\Teamspeak\TS3Config. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
41
		$this->logger = $logger ?? new NullLogger;
42
	}
43
44
	/**
45
	 *
46
	 */
47
	public function __destruct(){
48
		$this->disconnect();
49
	}
50
51
	/**
52
	 * @throws \chillerlan\Teamspeak\TS3ClientException
53
	 */
54
	public function connect():TS3Client{
55
56
		if(is_resource($this->socket)){
57
			return $this;
58
		}
59
60
		/** @phan-suppress-next-line PhanTypeMismatchArgumentInternal stupid inconsistent callables... */
61
		set_error_handler(function($severity, $msg, $file, $line){
62
			throw new ErrorException($msg, 0, $severity, $file, $line);
63
		});
64
65
		try{
66
			$this->socket = fsockopen($this->config->host, $this->config->port);
67
		}
68
		catch(Throwable $e){
69
			throw new TS3ClientException('could not connect: #'.$e->getMessage());
70
		}
71
72
		restore_error_handler();
73
		stream_set_timeout($this->socket, 1);
74
75
		$this->send('login client_login_name='.$this->config->query_user.' client_login_password='.$this->config->query_password);
76
		$this->send('use sid='.$this->config->vserver);
77
78
		return $this;
79
	}
80
81
	/**
82
	 * @return \chillerlan\Teamspeak\TS3Client
83
	 */
84
	public function disconnect():TS3Client{
85
86
		if(is_resource($this->socket)){
87
			$this->send('logout');
88
			$this->send('quit');
89
90
			fclose($this->socket);
91
92
			// just in case the destructor runs into this when the socket is already closed.
93
			$this->socket = null;
94
		}
95
96
		return $this;
97
	}
98
99
	/**
100
	 * @param string $command
101
	 *
102
	 * @return \chillerlan\Teamspeak\TS3Response
103
	 * @throws \chillerlan\Teamspeak\TS3ClientException
104
	 */
105
	public function send(string $command):TS3Response{
106
		$this->logger->debug('command: '.$command);
107
108
		if(!$this->socket){
109
			throw new TS3ClientException('not connected');
110
		}
111
112
		$command = trim($command);
113
114
		if(empty($command)){
115
			throw new TS3ClientException('empty command');
116
		}
117
118
		if(fwrite($this->socket, $command."\n") !== false){
119
			$response = stream_get_contents($this->socket);
120
121
			$this->logger->debug('response: '.$response);
122
123
			return new TS3Response($command, $response);
124
		}
125
126
		throw new TS3ClientException('could not send command: '.$command);
127
	}
128
129
}
130