ts3phpframework
Loading...
Searching...
No Matches
Node.php
Go to the documentation of this file.
1<?php
2
3namespace PlanetTeamSpeak\TeamSpeak3Framework\Node;
4
5use ArrayAccess;
6use Countable;
7use PlanetTeamSpeak\TeamSpeak3Framework\Adapter\ServerQuery;
8use PlanetTeamSpeak\TeamSpeak3Framework\Adapter\ServerQuery\Reply;
9use PlanetTeamSpeak\TeamSpeak3Framework\Exception\AdapterException;
10use PlanetTeamSpeak\TeamSpeak3Framework\Exception\NodeException;
11use PlanetTeamSpeak\TeamSpeak3Framework\Exception\ServerQueryException;
12use PlanetTeamSpeak\TeamSpeak3Framework\Helper\Convert;
13use PlanetTeamSpeak\TeamSpeak3Framework\Helper\StringHelper;
14use PlanetTeamSpeak\TeamSpeak3Framework\Viewer\ViewerInterface;
15use RecursiveIterator;
16use RecursiveIteratorIterator;
17
24abstract class Node implements RecursiveIterator, ArrayAccess, Countable
25{
29 protected Node|null|ServerQuery $parent = null;
30
34 protected array|null $server = null;
35
39 protected int $nodeId = 0x00;
40
44 protected array|null $nodeList = null;
45
49 protected array $nodeInfo = [];
50
54 protected array $storage = [];
55
64 public function request(string $cmd, bool $throw = true): Reply
65 {
66 return $this->getParent()->request($cmd, $throw);
67 }
68
76 public function prepare(string $cmd, array $params = []): StringHelper
77 {
78 return StringHelper::factory($this->getParent()->prepare($cmd, $params));
79 }
80
90 public function execute($cmd, array $params = []): Reply
91 {
92 return $this->request($this->prepare($cmd, $params));
93 }
94
100 public function getParent(): ServerQuery|Node|null
101 {
102 return $this->parent;
103 }
104
110 public function getId(): int
111 {
112 return $this->nodeId;
113 }
114
121 public function iconIsLocal(string $key): bool
122 {
123 $iconid = $this[$key];
124 if (!is_int($iconid)) {
125 $iconid = $iconid->toInt();
126 }
127
128 return $iconid > 0 && $iconid < 1000;
129 }
130
137 public function iconGetName(string $key): StringHelper
138 {
139 $iconid = $this[$key];
140 if (!is_int($iconid)) {
141 $iconid = $iconid->toInt();
142 }
143
144 $iconid = ($iconid < 0) ? (pow(2, 32)) - ($iconid * -1) : $iconid;
145
146 return new StringHelper("/icon_" . $iconid);
147 }
148
155 public function getClass(string $prefix = "ts3_"): string
156 {
157 if ($this instanceof Channel && $this->isSpacer()) {
158 return $prefix . "spacer";
159 } elseif ($this instanceof Client && $this["client_type"]) {
160 return $prefix . "query";
161 }
162
163 return $prefix . StringHelper::factory(get_class($this))->section("_", 2)->toLower();
164 }
165
171 abstract public function getUniqueId(): string;
172
178 abstract public function getIcon(): string;
179
185 abstract public function getSymbol(): string;
186
193 public function getViewer(ViewerInterface $viewer): string
194 {
195 $html = $viewer->fetchObject($this);
196
197 $iterator = new RecursiveIteratorIterator($this, RecursiveIteratorIterator::SELF_FIRST);
198
199 foreach ($iterator as $node) {
200 $siblings = [];
201
202 for ($level = 0; $level < $iterator->getDepth(); $level++) {
203 $siblings[] = ($iterator->getSubIterator($level)->hasNext()) ? 1 : 0;
204 }
205
206 $siblings[] = (!$iterator->getSubIterator($level)->hasNext()) ? 1 : 0;
207
208 $html .= $viewer->fetchObject($node, $siblings);
209 }
210
211 if (empty($html) && method_exists($viewer, "toString")) {
212 return $viewer->toString();
213 }
214
215 return $html;
216 }
217
225 protected function filterList(array $nodes = [], array $rules = []): array
226 {
227 if (!empty($rules)) {
228 foreach ($nodes as $node) {
229 if (!$node instanceof Node) {
230 continue;
231 }
232
233 $props = $node->getInfo(false);
234 $props = array_intersect_key($props, $rules);
235
236 foreach ($props as $key => $val) {
237 if ($val instanceof StringHelper) {
238 $match = $val->contains($rules[$key], true);
239 } else {
240 $match = $val == $rules[$key];
241 }
242
243 if ($match === false) {
244 unset($nodes[$node->getId()]);
245 }
246 }
247 }
248 }
249
250 return $nodes;
251 }
252
261 public function getInfo(bool $extend = true, bool $convert = false): array
262 {
263 if ($extend) {
264 $this->fetchNodeInfo();
265 }
266
267 if ($convert) {
268 $info = $this->nodeInfo;
269
270 foreach ($info as $key => $val) {
271 $key = StringHelper::factory($key);
272
273 if ($key->contains("_bytes_")) {
274 $info[$key->toString()] = Convert::bytes($val);
275 } elseif ($key->contains("_bandwidth_")) {
276 $info[$key->toString()] = Convert::bytes($val) . "/s";
277 } elseif ($key->contains("_packets_")) {
278 $info[$key->toString()] = number_format($val, 0, null, ".");
279 } elseif ($key->contains("_packetloss_")) {
280 $info[$key->toString()] = sprintf("%01.2f", floatval($val instanceof StringHelper ? $val->toString() : strval($val)) * 100) . "%";
281 } elseif ($key->endsWith("_uptime")) {
282 $info[$key->toString()] = Convert::seconds($val);
283 } elseif ($key->endsWith("_version")) {
284 $info[$key->toString()] = Convert::version($val);
285 } elseif ($key->endsWith("_icon_id")) {
286 $info[$key->toString()] = $this->iconGetName($key)->filterDigits();
287 }
288 }
289
290 return $info;
291 }
292
293 return $this->nodeInfo;
294 }
295
303 public function getProperty(string $property, mixed $default = null): mixed
304 {
305 if (!$this->offsetExists($property)) {
306 $this->fetchNodeInfo();
307 }
308
309 if (!$this->offsetExists($property)) {
310 return $default;
311 }
312
313 return $this->nodeInfo[$property];
314 }
315
321 public function __toString()
322 {
323 return get_class($this);
324 }
325
331 public function toString(): string
332 {
333 return $this->__toString();
334 }
335
341 public function toArray(): array
342 {
343 return $this->nodeList;
344 }
345
354 public function __call(string $name, array $args)
355 {
356 if ($this->getParent() instanceof Node) {
357 return call_user_func_array([$this->getParent(), $name], $args);
358 }
359
360 throw new NodeException("node method '" . $name . "()' does not exist");
361 }
362
370 protected function setStorage(string $key, mixed $val): void
371 {
372 $this->storage[$key] = $val;
373 }
374
382 protected function getStorage(string $key, mixed $default = null): mixed
383 {
384 return !empty($this->storage[$key]) ? $this->storage[$key] : $default;
385 }
386
393 protected function delStorage(string $key): void
394 {
395 unset($this->storage[$key]);
396 }
397
403 public function __sleep()
404 {
405 return ["parent", "storage", "nodeId"];
406 }
407
411 protected function fetchNodeList()
412 {
413 $this->nodeList = [];
414 }
415
419 protected function fetchNodeInfo()
420 {
421 }
422
426 protected function resetNodeInfo()
427 {
428 $this->nodeInfo = [];
429 }
430
434 protected function verifyNodeList()
435 {
436 if ($this->nodeList === null) {
437 $this->fetchNodeList();
438 }
439 }
440
444 protected function resetNodeList()
445 {
446 $this->nodeList = null;
447 }
448
452 public function count(): int
453 {
454 $this->verifyNodeList();
455
456 return count($this->nodeList);
457 }
458
462 public function current(): mixed
463 {
464 $this->verifyNodeList();
465
466 return current($this->nodeList);
467 }
468
472 public function getChildren(): null|RecursiveIterator
473 {
474 $this->verifyNodeList();
475
476 return $this->current();
477 }
478
482 public function hasChildren(): bool
483 {
484 $this->verifyNodeList();
485
486 return $this->current()->count() > 0;
487 }
488
492 public function hasNext(): bool
493 {
494 $this->verifyNodeList();
495
496 return $this->key() + 1 < $this->count();
497 }
498
502 public function key(): string|int|null
503 {
504 $this->verifyNodeList();
505
506 return key($this->nodeList);
507 }
508
512 public function valid(): bool
513 {
514 $this->verifyNodeList();
515
516 return $this->key() !== null;
517 }
518
522 public function next(): void
523 {
524 $this->verifyNodeList();
525
526 next($this->nodeList);
527 }
528
532 public function rewind(): void
533 {
534 $this->verifyNodeList();
535
536 reset($this->nodeList);
537 }
538
542 public function offsetExists($offset): bool
543 {
544 return array_key_exists((string)$offset, $this->nodeInfo);
545 }
546
551 public function offsetGet($offset): mixed
552 {
553 if (!$this->offsetExists($offset)) {
554 $this->fetchNodeInfo();
555 }
556
557 if (!$this->offsetExists($offset)) {
558 throw new NodeException("node '" . get_class($this) . "' has no property named '" . $offset . "'");
559 }
560
561 return $this->nodeInfo[(string)$offset];
562 }
563
568 public function offsetSet($offset, $value): void
569 {
570 if (method_exists($this, "modify")) {
571 $this->modify([(string)$offset => $value]);
572 return;
573 }
574
575 throw new NodeException("node '" . get_class($this) . "' is read only");
576 }
577
581 public function offsetUnset($offset): void
582 {
583 unset($this->nodeInfo[(string)$offset]);
584 }
585
590 public function __get($offset)
591 {
592 return $this->offsetGet($offset);
593 }
594
599 public function __set($offset, $value)
600 {
601 $this->offsetSet($offset, $value);
602 }
603}
Provides methods to analyze and format a ServerQuery reply.
Definition Reply.php:19
Enhanced exception class for PlanetTeamSpeak\TeamSpeak3Framework\Node\Node objects.
Class describing a TeamSpeak 3 channel and all it's parameters.
Definition Channel.php:18
Class describing a TeamSpeak 3 client and all it's parameters.
Definition Client.php:18
__call(string $name, array $args)
Definition Node.php:354
filterList(array $nodes=[], array $rules=[])
Definition Node.php:225
request(string $cmd, bool $throw=true)
Definition Node.php:64
getViewer(ViewerInterface $viewer)
Definition Node.php:193
getStorage(string $key, mixed $default=null)
Definition Node.php:382
setStorage(string $key, mixed $val)
Definition Node.php:370
getInfo(bool $extend=true, bool $convert=false)
Definition Node.php:261
getProperty(string $property, mixed $default=null)
Definition Node.php:303
prepare(string $cmd, array $params=[])
Definition Node.php:76