diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 3dc76fd..cc7595b 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -25,6 +25,8 @@ jobs: run: php vendor/bin/phpcs --standard=phpcs.xml - name: "Run PHP Unit Test" run: php vendor/bin/phpunit --configuration=phpunit.xml + - name: "Run Phpstan" + run: php vendor/bin/phpstan --configuration=phpstan.neon --memory-limit=256M continuous-integration-php82: name: "Continuous Integration php8.2" runs-on: ubuntu-latest @@ -45,6 +47,8 @@ jobs: run: php vendor/bin/phpcs --standard=phpcs.xml - name: "Run PHP Unit Test" run: php vendor/bin/phpunit --configuration=phpunit.xml + - name: "Run Phpstan" + run: php vendor/bin/phpstan --configuration=phpstan.neon --memory-limit=256M coding-standards-php83: name: "Continuous Integration php8.3" runs-on: ubuntu-latest @@ -65,3 +69,5 @@ jobs: run: php vendor/bin/phpcs --standard=phpcs.xml - name: "Run PHP Unit Test" run: php vendor/bin/phpunit --configuration=phpunit.xml + - name: "Run Phpstan" + run: php vendor/bin/phpstan --configuration=phpstan.neon --memory-limit=256M diff --git a/README.md b/README.md index 7147c57..3e17b28 100644 --- a/README.md +++ b/README.md @@ -35,13 +35,13 @@ $resolver = new Resolver($dnsServer, $cache); */ $useCache = true; // default to true $timeout = 3.5; // 3.5 seconds -$response = $resolver->lookup('domainname.ext', 'A', 'IN', $timeout, $useCache); +$response = $resolver->lookup('domain-name.ext', 'A', 'IN', $timeout, $useCache); /** * Enable Pseudo OPT */ $resolver->setDnsSec(true); -$response = $resolver->lookup('domainname.ext', 'A', 'IN'); +$response = $resolver->lookup('domain-name.ext', 'A', 'IN'); $answers = $response->getAnswers(); $records = $answers->getRecords(); // Filter "A" Address Only @@ -49,7 +49,7 @@ $arrayA = $records->getFilteredType('A'); ``` -> IXFR & AXFR not yet implemented +> IXFR & AXFR aren't fully implemented yet ## Note diff --git a/src/Abstracts/AbstractDnsServer.php b/src/Abstracts/AbstractDnsServer.php index e771d44..5231757 100644 --- a/src/Abstracts/AbstractDnsServer.php +++ b/src/Abstracts/AbstractDnsServer.php @@ -64,7 +64,7 @@ public function getSecondaryServer(): ?string public function getName(): string { // fallback default class name - return $this->name ??= ltrim(strrchr($this::class, '\\'))?:$this::class; + return $this->name ??= ltrim(strrchr($this::class, '\\')?:$this::class)?:$this::class; } /** @@ -97,6 +97,15 @@ public function unserialize(string $data) : void $this->__unserialize(unserialize($data)); } + /** + * @return array{ + * identity:string, + * name: string, + * primaryServer: string, + * secondaryServer: ?string, + * port: int, + * } + */ public function __serialize(): array { return [ @@ -111,7 +120,13 @@ public function __serialize(): array /** * Magic method for unserialize * - * @param array $data + * @param array{ + * identity:string, + * name: string, + * primaryServer: string, + * secondaryServer: ?string, + * port: int, + * } $data * @return void */ public function __unserialize(array $data): void diff --git a/src/Abstracts/AbstractResourceRecordType.php b/src/Abstracts/AbstractResourceRecordType.php index e30a567..29dce6a 100644 --- a/src/Abstracts/AbstractResourceRecordType.php +++ b/src/Abstracts/AbstractResourceRecordType.php @@ -10,10 +10,9 @@ use ArrayAccess\DnsRecord\Interfaces\ResourceRecord\ResourceRecordMetaTypeInterface; use ArrayAccess\DnsRecord\Interfaces\ResourceRecord\ResourceRecordQTypeDefinitionInterface; use ArrayAccess\DnsRecord\Interfaces\ResourceRecord\ResourceRecordTypeInterface; -use ArrayAccess\DnsRecord\ResourceRecord\Definitions\QType; use ArrayAccess\DnsRecord\Utils\Buffer; use ArrayAccess\DnsRecord\Utils\Lookup; -use function is_string; +use function is_array; use function ord; use function serialize; use function sprintf; @@ -47,11 +46,11 @@ abstract class AbstractResourceRecordType implements ResourceRecordTypeInterface /** * Response type * - * @var string|ResourceRecordQTypeDefinitionInterface + * @var ResourceRecordQTypeDefinitionInterface * @see ResourceRecordTypeInterface::getType() * @see Lookup::RR_TYPES */ - protected ResourceRecordQTypeDefinitionInterface|string $type; + protected ResourceRecordQTypeDefinitionInterface $type; /** * @var ResourceRecordClassInterface @@ -112,10 +111,6 @@ public function getOffsetPosition(): int protected function parseMessage(): void { $type = static::TYPE; - if (!isset($this->type) && is_string($type)) { - $this->type = $type; - } - $message = $this->message->getMessage(); $offsetPosition = $this->offsetPosition; $this->name = Buffer::readLabel($message, $offsetPosition); @@ -125,12 +120,17 @@ protected function parseMessage(): void 'Response header length is invalid' ); } - [ - 'type' => $type, - 'class' => $class, - 'ttl' => $this->ttl, - 'length' => $this->rdLength, - ] = unpack("ntype/nclass/Nttl/nlength", $this->header); + $headerArray = unpack("ntype/nclass/Nttl/nlength", $this->header); + $this->rdLength = 0; + if (is_array($headerArray)) { + [ + 'type' => $type, + 'class' => $class, + 'ttl' => $this->ttl, + 'length' => $this->rdLength, + ] = $headerArray; + } + $this->rData = substr($message, $offsetPosition, $this->rdLength); if (strlen($this->rData) !== $this->rdLength) { throw new LengthException( @@ -138,15 +138,14 @@ protected function parseMessage(): void ); } - $type = Lookup::resourceType($type); - $class = Lookup::resourceClass($class); - if (isset($this->type)) { - $originType = $this->getType(); - if ($originType->getName() !== $type->getName()) { + $type = $type ? Lookup::resourceType($type) : null; + $class = Lookup::resourceClass($class??''); + if (isset($this->type) || !$type) { + if ($this->type->getName() !== $type?->getName()) { throw new MalformedDataException( sprintf( 'Response type does not match with current object type. object type: [%s] response type: [%s]', - $originType, + $this->type->getName(), $type ) ); @@ -165,6 +164,7 @@ protected function parseMessage(): void * @param string $message * @param int $rdataOffset * @noinspection PhpMissingReturnTypeInspection + * @phpstan-ignore-next-line */ protected function parseRData(string $message, int $rdataOffset) { @@ -212,11 +212,6 @@ public function getMessage(): PacketMessageInterface */ public function getType(): ResourceRecordQTypeDefinitionInterface { - if (isset($this->type)) { - is_string($this->type) && $this->type = QType::create($this->type); - return $this->type; - } - return $this->type; } @@ -294,7 +289,7 @@ public function __serialize(): array /** * Magic method for unserialize * - * @param array $data + * @param array{message: PacketMessageInterface, offsetPosition: int} $data * @return void * @throws MalformedDataException */ diff --git a/src/Cache/Adapter/FileCacheAdapter.php b/src/Cache/Adapter/FileCacheAdapter.php index 3e4d20f..6e6b3db 100644 --- a/src/Cache/Adapter/FileCacheAdapter.php +++ b/src/Cache/Adapter/FileCacheAdapter.php @@ -29,6 +29,7 @@ use function is_dir; use function is_file; use function is_int; +use function is_resource; use function is_string; use function md5; use function preg_match; @@ -38,6 +39,7 @@ use function restore_error_handler; use function serialize; use function set_error_handler; +use function sprintf; use function str_replace; use function strlen; use function substr; @@ -139,9 +141,10 @@ private function doInit(string $namespace, ?string $directory): void { $namespace = trim($namespace); $namespace = preg_replace('~[^a-z0-9_\-.]~i', '', $namespace); - if ($namespace === '') { + if (!$namespace || !is_string($namespace)) { $namespace = '@'; } + if (!$directory || trim($directory) === '' || trim(trim($directory), '/\\') === '' @@ -187,12 +190,17 @@ private static function isOpcacheSupport(): bool ); } + /** + * @param string $directory + * @param bool $loopDir + * @return Generator + */ private function scanFiles(string $directory, bool $loopDir = false) : Generator { if (!is_dir($directory)) { return ''; } - $directory = rtrim(realpath($directory)??$directory, '\\/'); + $directory = rtrim(realpath($directory)?:$directory, '\\/'); $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $length = strlen($chars); for ($i = 0; $i < $length; ++$i) { @@ -235,9 +243,12 @@ public function prune(): bool } $value = null; $valid = $this->validatePartialFile($file); + if (!$valid) { + $this->doUnlink($file); + continue; + } try { - if ($valid - && is_array(($expiresAt = include $file)) + if (is_array(($expiresAt = include $file)) && count($expiresAt) === 3 && is_int($expiresAt[0]??null) && is_string($expiresAt[1]??null) @@ -285,7 +296,7 @@ private function clearLocalCache(): void } if (count($this->files) > $maximum) { while (count($this->files) > $max) { - array_shift(self::$cachesExpires); + array_shift($this->files); } } } @@ -359,7 +370,14 @@ private function write(string $file, string $data) : bool $tmp = $this->generateTempFile(); $h = fopen($tmp, 'x'); } - + if (!is_resource($h)) { + throw new Exception( + sprintf( + 'Canot create resource from file : %s', + $tmp + ) + ); + } fwrite($h, $data); fclose($h); $unlink = true; @@ -426,7 +444,7 @@ private function doDelete(string $id, string ...$ids) : bool return $this->doIdDelete(...$arrayId); } - private function doUnlink(string $file) + private function doUnlink(string $file) : bool { if (self::isOpcacheSupport()) { Caller::call('opcache_invalidate', $file, true); @@ -508,7 +526,7 @@ private function doFetch(string $key): ?CacheDataInterface $unlink = true; return null; } finally { - if ($unlink && file_exists($file)) { + if ($unlink) { self::$cachesExpires[$file] = 0; unset($this->values[$key]); $this->doUnlink($file); @@ -559,7 +577,7 @@ public function getItem(string $key): CacheDataInterface if (isset($this->values[$key])) { return $this->values[$key]; } - return $this->doFetch($key)??(new CacheData($key))->expiresAt( + return $this->doFetch($key)??(new CacheData($key))->expiresAfter( $this->defaultLifetime === 0 ? null : $this->defaultLifetime diff --git a/src/Cache/Adapter/Psr6CacheAdapter.php b/src/Cache/Adapter/Psr6CacheAdapter.php index 18701de..4cea758 100644 --- a/src/Cache/Adapter/Psr6CacheAdapter.php +++ b/src/Cache/Adapter/Psr6CacheAdapter.php @@ -60,7 +60,7 @@ public function saveItem(CacheDataInterface $cacheData): bool $item ->set($cacheData) ->expiresAfter($cacheData->getExpiresAfter()); - return $this->getCacheItemPool()->save($item); + return $this->getCacheItemPool()?->save($item)??false; } /** @@ -95,7 +95,7 @@ public function deleteItems(string ...$keys): bool public function getItem(string $key): CacheDataInterface { $cacheItem = $this->getCacheItem($key); - $cacheItem = $cacheItem->get(); + $cacheItem = $cacheItem?->get(); if ($cacheItem instanceof CacheDataInterface) { return $cacheItem; } diff --git a/src/Cache/CacheData.php b/src/Cache/CacheData.php index 15659bb..934534f 100644 --- a/src/Cache/CacheData.php +++ b/src/Cache/CacheData.php @@ -3,12 +3,9 @@ namespace ArrayAccess\DnsRecord\Cache; -use ArrayAccess\DnsRecord\Exceptions\CacheException; use ArrayAccess\DnsRecord\Interfaces\Cache\CacheDataInterface; use DateInterval; use DateTimeInterface; -use function is_array; -use function is_string; use function serialize; use function unserialize; @@ -121,23 +118,20 @@ public function serialize(): string /** * @inheritdoc - * @throws CacheException */ public function unserialize(string $data): void { - $data = unserialize($data); - if (!is_array($data) || !is_string($data['key']??null)) { - throw new CacheException( - 'Invalid serialized data' - ); - } - $this->__unserialize($data); + $this->__unserialize(unserialize($data)); } /** * Magic method for unserialize * - * @param array $data + * @param array{ + * key: string, + * data: mixed, + * ttl: ?int + * } $data * @return void */ public function __unserialize(array $data): void @@ -150,7 +144,7 @@ public function __unserialize(array $data): void /** * Magic method for serializing * - * @return array{key: string, data: mixed, ttl:int} + * @return array{key: string, data: mixed, ttl: ?int} */ public function __serialize(): array { diff --git a/src/DnsServer/CustomDnsServer.php b/src/DnsServer/CustomDnsServer.php index 0433303..c3804b8 100644 --- a/src/DnsServer/CustomDnsServer.php +++ b/src/DnsServer/CustomDnsServer.php @@ -10,7 +10,7 @@ /** * User defined dns server */ -class CustomDnsServer extends AbstractDnsServer +final class CustomDnsServer extends AbstractDnsServer { use DisableSetterTrait; diff --git a/src/DnsServerStorage.php b/src/DnsServerStorage.php index c5cf51f..563e0fd 100644 --- a/src/DnsServerStorage.php +++ b/src/DnsServerStorage.php @@ -32,12 +32,12 @@ class DnsServerStorage implements DnsServerStorageInterface ]; /** - * @var array + * @var DnsServerInterface[] */ protected array $servers = []; /** - * @var array + * @var array> */ private static array $cachedDefaultServers = []; @@ -79,13 +79,19 @@ public static function createDefault() : static { $obj = null; foreach (self::DEFAULT_SERVER as $className) { + $server = self::getDefaultServer($className); + if (!$server) { + continue; + } if (!$obj) { - $obj = new static(self::getDefaultServer($className)); + $obj = new static($server); continue; } - $obj->add(self::getDefaultServer($className)); + $obj->add($server); } - + /** + * @var static $obj + */ return $obj; } @@ -168,7 +174,7 @@ public function __serialize(): array /** * Magic method unserialize * - * @param array $data + * @param array{servers: DnsServerInterface[]} $data * @return void */ public function __unserialize(array $data): void diff --git a/src/Interfaces/Cache/CacheStorageInterface.php b/src/Interfaces/Cache/CacheStorageInterface.php index ce272a6..989059c 100644 --- a/src/Interfaces/Cache/CacheStorageInterface.php +++ b/src/Interfaces/Cache/CacheStorageInterface.php @@ -30,6 +30,7 @@ public function getAdapter() : ?CacheAdapterInterface; * Set cache adapter * * @param CacheAdapterInterface $cacheAdapter + * @phpstan-ignore-next-line */ public function setAdapter(CacheAdapterInterface $cacheAdapter); diff --git a/src/Interfaces/DnsServer/DnsServerStorageInterface.php b/src/Interfaces/DnsServer/DnsServerStorageInterface.php index 759ffe2..443a1c6 100644 --- a/src/Interfaces/DnsServer/DnsServerStorageInterface.php +++ b/src/Interfaces/DnsServer/DnsServerStorageInterface.php @@ -29,6 +29,7 @@ public static function createDefault() : static; * Append dns server into collections * * @param DnsServerInterface $server + * @phpstan-ignore-next-line */ public function add(DnsServerInterface $server); @@ -36,6 +37,7 @@ public function add(DnsServerInterface $server); * Remove dns server * * @param DnsServerInterface|string $server + * @phpstan-ignore-next-line */ public function remove(DnsServerInterface|string $server); @@ -55,7 +57,7 @@ public function get(DnsServerInterface|string $server): ?DnsServerInterface; public function getServers(): array; /** - * @return Traversable + * @return Traversable */ public function getIterator() : Traversable; } diff --git a/src/Interfaces/Packet/PacketHeaderInterface.php b/src/Interfaces/Packet/PacketHeaderInterface.php index 0f931aa..90e9826 100644 --- a/src/Interfaces/Packet/PacketHeaderInterface.php +++ b/src/Interfaces/Packet/PacketHeaderInterface.php @@ -37,9 +37,9 @@ interface PacketHeaderInterface extends Serializable * Create a new Header object from given raw data * * @param PacketMessageInterface|string $message the raw message from dns response - * @return static + * @return PacketHeaderInterface */ - public static function fromMessage(PacketMessageInterface|string $message): static; + public static function fromMessage(PacketMessageInterface|string $message): PacketHeaderInterface; /** * Crate query header for request dns server @@ -81,7 +81,7 @@ public function getId(): int; * A one-bit field that specifies whether this message is a * query (0), or a response (1) * - * @return int<0|1> + * @return int Lookup::QR_RESPONSE|Lookup::QR_QUERY */ public function getQR(): int; diff --git a/src/Interfaces/Packet/PacketQuestionInterface.php b/src/Interfaces/Packet/PacketQuestionInterface.php index 434f4c1..8309513 100644 --- a/src/Interfaces/Packet/PacketQuestionInterface.php +++ b/src/Interfaces/Packet/PacketQuestionInterface.php @@ -14,12 +14,12 @@ interface PacketQuestionInterface extends Serializable * Question constructor * * @param string $name QNAME / Name - * @param string|Int|ResourceRecordTypeInterface $type QTYPE / Type + * @param string|Int|ResourceRecordTypeInterface|ResourceRecordQTypeDefinitionInterface $type QTYPE / Type * @param string|int|ResourceRecordClassInterface $class QCLASS / Class */ public function __construct( string $name, - string|Int|ResourceRecordTypeInterface $type, + string|Int|ResourceRecordTypeInterface|ResourceRecordQTypeDefinitionInterface $type, string|int|ResourceRecordClassInterface $class ); diff --git a/src/Interfaces/Packet/PacketResourceRecordsInterface.php b/src/Interfaces/Packet/PacketResourceRecordsInterface.php index 6e9d0e2..c12a658 100644 --- a/src/Interfaces/Packet/PacketResourceRecordsInterface.php +++ b/src/Interfaces/Packet/PacketResourceRecordsInterface.php @@ -20,6 +20,7 @@ interface PacketResourceRecordsInterface extends IteratorAggregate, Countable, S * Add record * * @param ResourceRecordTypeInterface $record + * @phpstan-ignore-next-line */ public function add(ResourceRecordTypeInterface $record); @@ -27,6 +28,7 @@ public function add(ResourceRecordTypeInterface $record); * Remove record * * @param ResourceRecordTypeInterface $record + * @phpstan-ignore-next-line */ public function remove(ResourceRecordTypeInterface $record); @@ -42,19 +44,20 @@ public function getRecords(): array; * * @param string $type * @param bool $single - * @return array|ResourceRecordTypeInterface|null + * @return array|ResourceRecordTypeInterface|null */ public function getFilteredType(string $type, bool $single = false) : null|array|ResourceRecordTypeInterface; /** * Return array records + * * @uses ResourceRecordTypeInterface::toArray() - * @return array + * @return array> */ public function toArray() : array; /** - * @return Traversable + * @return Traversable */ public function getIterator(): Traversable; } diff --git a/src/Interfaces/Packet/PacketResponseInterface.php b/src/Interfaces/Packet/PacketResponseInterface.php index b89e15e..f72eaea 100644 --- a/src/Interfaces/Packet/PacketResponseInterface.php +++ b/src/Interfaces/Packet/PacketResponseInterface.php @@ -22,7 +22,7 @@ public function getPacketData() : PacketRequestDataInterface; /** * Get used protocol * - * @return string<"udp"|"tcp"> + * @return string udp or tcp */ public function getProtocol() : string; @@ -64,7 +64,7 @@ public function getAnswers() : PacketAnswersInterface; public function getStartTime() : float; /** - * Get end of query time + * Get the end of query time * * @return float */ diff --git a/src/Interfaces/ResourceRecord/ResourceRecordTypeInterface.php b/src/Interfaces/ResourceRecord/ResourceRecordTypeInterface.php index 56cee37..4546aee 100644 --- a/src/Interfaces/ResourceRecord/ResourceRecordTypeInterface.php +++ b/src/Interfaces/ResourceRecord/ResourceRecordTypeInterface.php @@ -121,6 +121,7 @@ public function getRDLength() : int; /** * Resource data + * @phpstan-ignore-next-line */ public function getValue(); @@ -141,7 +142,7 @@ public function getQueryMessage() : string; /** * Return array data * - * @return array like dns_get_record() + * @return array like dns_get_record() * @see \dns_get_record() */ public function toArray() : array; diff --git a/src/Packet/Answers.php b/src/Packet/Answers.php index 5486039..36a717e 100644 --- a/src/Packet/Answers.php +++ b/src/Packet/Answers.php @@ -110,6 +110,7 @@ private function parseHeader(): PacketHeaderInterface * Parse the response question * * @throws MalformedDataException + * @return PacketQuestionInterface[] */ private function parseQuestions() : array { @@ -155,9 +156,10 @@ private function parseQuestions() : array /** * Parse the records * + * @return PacketResourceRecordsInterface * @throws MalformedDataException */ - private function parseRecords() : Records + private function parseRecords() : PacketResourceRecordsInterface { if (isset($this->records)) { return $this->records; @@ -308,7 +310,7 @@ public function unserialize(string $data): void /** * Magic method for serializing * - * @return array{message: Message} + * @return array{message: PacketMessageInterface} */ public function __serialize(): array { @@ -318,7 +320,7 @@ public function __serialize(): array /** * Magic method for unserialize * - * @param array $data + * @param array{message: PacketMessageInterface} $data * @return void */ public function __unserialize(array $data): void diff --git a/src/Packet/Header.php b/src/Packet/Header.php index c3acf4c..8629f15 100644 --- a/src/Packet/Header.php +++ b/src/Packet/Header.php @@ -203,7 +203,7 @@ public function __toString(): string * Parse the message * * @param string $message - * @return $this + * @return static */ private function parseMessage(string $message) : static { @@ -251,7 +251,7 @@ private function parseMessage(string $message) : static /** * @inheritdoc */ - public static function fromMessage(PacketMessageInterface|string $message): static + public static function fromMessage(PacketMessageInterface|string $message): PacketHeaderInterface { if (!is_string($message)) { $message = $message->getMessage(); @@ -555,6 +555,7 @@ public function serialize(): string /** * @inheritdoc * @return void + * @throws \Exception */ public function unserialize(string $data): void { @@ -575,8 +576,9 @@ public function __serialize(): array /** * Magic method for unserialize * - * @param array $data + * @param array{message: string} $data * @return void + * @throws \Exception * @uses base64_decode() decode to raw data */ public function __unserialize(array $data): void diff --git a/src/Packet/Message.php b/src/Packet/Message.php index 6b47caa..4ca5dcc 100644 --- a/src/Packet/Message.php +++ b/src/Packet/Message.php @@ -64,7 +64,7 @@ public function __serialize(): array /** * Magic method for unserialize * - * @param array $data + * @param array{message: string} $data * @return void * @uses base64_decode() decode to raw data */ diff --git a/src/Packet/Question.php b/src/Packet/Question.php index dc46899..5db8c50 100644 --- a/src/Packet/Question.php +++ b/src/Packet/Question.php @@ -42,24 +42,24 @@ class Question implements PacketQuestionInterface * @see PacketQuestionInterface::getName() * @var string */ - public readonly string $name; + private string $name; /** * @see PacketQuestionInterface::getMessage() * @var string */ - public readonly string $message; + private string $message; /** * @see PacketQuestionInterface::getType() */ - public readonly ?ResourceRecordQTypeDefinitionInterface $type; + private ?ResourceRecordQTypeDefinitionInterface $type; /** * @see PacketQuestionInterface::getClass() * @var ?ResourceRecordClassInterface */ - public readonly ?ResourceRecordClassInterface $class; + private ?ResourceRecordClassInterface $class; /** * @inheritdoc @@ -103,7 +103,9 @@ private function initName(string $name, bool $internal = false): void } $name = strtolower($name); - if (($this->type??null) === 'PTR' && !preg_match('~\.(in-addr|ip6)\.arpa$~', $name)) { + if ($this->getType()?->getName() === 'PTR' + && !preg_match('~\.(in-addr|ip6)\.arpa$~', $name) + ) { $name = Addresses::reverseIp($name)??$name; } $this->name = $name; @@ -178,14 +180,18 @@ public function unserialize(string $data): void /** * Magic method for serializing * - * @return array{name:string, type:string, class:string} + * @return array{ + * name: string, + * type: string, + * class: string + * } */ public function __serialize(): array { return [ 'name' => $this->name, - 'type' => $this->type, - 'class' => $this->class, + 'type' => $this->getType()?->getName()??'', + 'class' => $this->getClass()?->getName()??'', ]; } @@ -224,7 +230,11 @@ public static function fromFilteredResponse( /** * Magic method for unserialize * - * @param array $data + * @param array{ + * name: string, + * type: string, + * class: string + * } $data * @return void */ public function __unserialize(array $data): void diff --git a/src/Packet/Records.php b/src/Packet/Records.php index 8a0916f..4b0e355 100644 --- a/src/Packet/Records.php +++ b/src/Packet/Records.php @@ -112,11 +112,17 @@ public function count(): int return count($this->records); } + /** + * @inheritdoc + */ public function serialize() : string { return serialize($this->__serialize()); } + /** + * @inheritdoc + */ public function unserialize(string $data): void { $this->__unserialize(unserialize($data)); @@ -137,11 +143,14 @@ public function __serialize(): array /** * Magic method for unserialize * - * @param array $data + * @param array{records: ResourceRecordTypeInterface[]} $data * @return void */ public function __unserialize(array $data): void { - $this->records = $data['records']; + $this->records = []; + foreach ($data['records'] as $record) { + $this->add($record); + } } } diff --git a/src/Packet/RequestData.php b/src/Packet/RequestData.php index 3f08be5..2bc8d92 100644 --- a/src/Packet/RequestData.php +++ b/src/Packet/RequestData.php @@ -16,6 +16,9 @@ class RequestData implements PacketRequestDataInterface { + /** + * @var PacketQuestionInterface[] + */ protected array $questions; protected PacketResourceRecordsInterface $additionalRecords; @@ -73,7 +76,7 @@ public function getQuestions(): array */ public function getQuestion(): PacketQuestionInterface { - return reset($this->questions); + return $this->getQuestions()[0]; } /** @@ -193,7 +196,12 @@ public function unserialize(string $data): void /** * Magic method for serializing * - * @return array + * @return array{ + * questions: PacketQuestionInterface[], + * additionalRecords: PacketResourceRecordsInterface, + * authorityRecords: PacketResourceRecordsInterface, + * answerRecords: PacketResourceRecordsInterface + * } */ public function __serialize(): array { @@ -208,7 +216,12 @@ public function __serialize(): array /** * Magic method for unserialize * - * @param array $data + * @param array{ + * questions: PacketQuestionInterface[], + * additionalRecords: PacketResourceRecordsInterface, + * authorityRecords: PacketResourceRecordsInterface, + * answerRecords: PacketResourceRecordsInterface + * } $data * @return void */ public function __unserialize(array $data): void diff --git a/src/Packet/RequestDataWrapper.php b/src/Packet/RequestDataWrapper.php index 67ad138..bff2d09 100644 --- a/src/Packet/RequestDataWrapper.php +++ b/src/Packet/RequestDataWrapper.php @@ -28,7 +28,7 @@ public function getHeader(): PacketHeaderInterface return $this->packetRequestData->getHeader(); } - public function withHeader(PacketHeaderInterface $header): static + public function withHeader(PacketHeaderInterface $header): RequestDataWrapper { return new self($this->packetRequestData->withHeader($header)); } @@ -123,7 +123,7 @@ public function __serialize(): array /** * Magic method unserialize * - * @param array $data + * @param array{packetRequestData: PacketRequestDataInterface} $data * @return void */ public function __unserialize(array $data): void diff --git a/src/Packet/Response.php b/src/Packet/Response.php index 48f6473..69dbda8 100644 --- a/src/Packet/Response.php +++ b/src/Packet/Response.php @@ -81,6 +81,18 @@ public function unserialize(string $data): void $this->__unserialize(unserialize($data)); } + /** + * @return array{ + * startTime: float, + * endTime: float, + * protocol: string, + * server: string, + * port: int, + * packetData: PacketRequestDataInterface, + * answers: PacketAnswersInterface, + * time: int + * } + */ public function __serialize(): array { return [ @@ -98,7 +110,16 @@ public function __serialize(): array /** * Magic method for unserialize * - * @param array $data + * @param array{ + * startTime: float, + * endTime: float, + * protocol: string, + * server: string, + * port: int, + * packetData: PacketRequestDataInterface, + * answers: PacketAnswersInterface, + * time: int + * } $data * @return void */ public function __unserialize(array $data): void diff --git a/src/Resolver.php b/src/Resolver.php index 195192f..909a69e 100644 --- a/src/Resolver.php +++ b/src/Resolver.php @@ -40,9 +40,9 @@ class Resolver protected bool $dnsSec = false; /** - * if we should set the recursion desired bit to 1 or 0. + * The recursion desired bit to 1 or 0. * - * by default, this is set to true, the DNS server to perform a recursive + * By default, this is set to true, the DNS server to perform a recursive * request. If set to false, the RD bit will be set to 0, and the server will * not perform recursion on the request. */ @@ -96,10 +96,7 @@ public function setRecurse(bool $recurse): void public function getCache(): CacheStorageInterface { - if (!isset($this->cache)) { - $this->setCache(new CacheStorage()); - } - return $this->cache; + return $this->cache ??= new CacheStorage(); } public function setCache(CacheStorageInterface $cache): void @@ -109,10 +106,7 @@ public function setCache(CacheStorageInterface $cache): void public function getDnsServerStorage(): DnsServerStorage { - if (!isset($this->dnsServerStorage)) { - $this->setDnsServerStorage(DnsServerStorage::createDefault()); - } - return $this->dnsServerStorage; + return $this->dnsServerStorage ??= DnsServerStorage::createDefault(); } public function setDnsServerStorage(DnsServerStorage $dnsServerStorage): void @@ -176,7 +170,7 @@ public function createQueryOpcode( if ($isOpt || $dnsSec) { $requestData ->getAdditionalRecords() - ->add(OPT::create($question->getType()->getValue())); + ->add(OPT::create($question->getType()?->getValue()??0)); } return $requestData; } @@ -201,6 +195,8 @@ public function query( $class, $this->isAdFlag(), $this->isCdFlag(), + $this->isDnsSec(), + $this->isRecurse(), ...$server ); } @@ -225,6 +221,8 @@ public function iQuery( $class, $this->isAdFlag(), $this->isCdFlag(), + $this->isDnsSec(), + $this->isRecurse(), ...$server ); } @@ -269,7 +267,7 @@ public function lookups( $udp = null; $cached = []; foreach ($requests as $key => $request) { - $name = $request->getQuestion()->getClass()->getName(); + $name = $request->getQuestion()->getClass()?->getName()??IN::NAME; if (isset($cached[$name])) { $requests[$key] = $cached[$name]; continue; @@ -291,6 +289,10 @@ public function lookups( ] = $this->createSocket($dns, false); } + /** + * @var resource $socket + * @var string $server + */ $socket = $isUdp ? $udp : $tcp; $server = $isUdp ? $udpServer : $tcpServer; $port = $isUdp ? $udpPort : $tcpPort; @@ -326,8 +328,8 @@ public function lookups( $startTime, $this->createMicrotime(), $protocol, - $server, - $port, + (string) $server, + (int) $port, $request, new Answers($message) ); @@ -343,6 +345,9 @@ public function lookups( $this->closeSocketResource($tcp); $this->closeSocketResource($udp); + /** + * @var array $requests + */ return $requests; } diff --git a/src/ResourceRecord/Definitions/QType.php b/src/ResourceRecord/Definitions/QType.php index 6c2ce51..845f370 100644 --- a/src/ResourceRecord/Definitions/QType.php +++ b/src/ResourceRecord/Definitions/QType.php @@ -17,6 +17,9 @@ final class QType implements ResourceRecordQTypeDefinitionInterface { use NamedValueTrait; + /** + * @var array + */ private static array $cachedObject = []; private function __construct(string $name, int $value) @@ -27,10 +30,10 @@ private function __construct(string $name, int $value) /** * @param int|string $key - * @return self + * @return QType * @throws InvalidArgumentException */ - public static function create(int|string $key) : self + public static function create(int|string $key) : QType { if (is_string($key)) { $key = strtoupper(trim($key)); @@ -66,6 +69,6 @@ public static function create(int|string $key) : self ) ); } - return self::$cachedObject[$value] ??= new self($value, $key); + return self::$cachedObject[$key] ??= new self($value, $key); } } diff --git a/src/ResourceRecord/RRTypes/AAAA.php b/src/ResourceRecord/RRTypes/AAAA.php index 0aa3ea8..8174c40 100644 --- a/src/ResourceRecord/RRTypes/AAAA.php +++ b/src/ResourceRecord/RRTypes/AAAA.php @@ -44,7 +44,7 @@ public function getAddress(): string * class: string, * ttl: int, * type: string, - * ip: string + * ipv6: string * } */ public function toArray(): array diff --git a/src/ResourceRecord/RRTypes/CAA.php b/src/ResourceRecord/RRTypes/CAA.php index d0f600d..bd47350 100644 --- a/src/ResourceRecord/RRTypes/CAA.php +++ b/src/ResourceRecord/RRTypes/CAA.php @@ -4,7 +4,9 @@ namespace ArrayAccess\DnsRecord\ResourceRecord\RRTypes; use ArrayAccess\DnsRecord\Abstracts\AbstractResourceRecordType; +use function is_array; use function substr; +use function unpack; /** * DNS Certification Authority Authorization (CAA) Resource Record - CAA RFC6844 @@ -27,29 +29,32 @@ class CAA extends AbstractResourceRecordType /** * @var int */ - protected int $flags; + protected int $flags = 0; /** * @var string */ - protected string $tag; + protected string $tag = ''; /** * @var int */ - protected int $tagLength; + protected int $tagLength = 0; /** * @inheritdoc */ protected function parseRData(string $message, int $rdataOffset): void { + $data = unpack('Cflags/CtagLength', substr($this->rData, 0, 2)); + if (!is_array($data)) { + return; + } // unpack the flags and tag length [ 'flags' => $this->flags, 'tagLength' => $this->tagLength, - - ] = unpack('Cflags/CtagLength', substr($this->rData, 0, 2)); + ] = $data; $this->tag = substr($this->rData, 2, $this->tagLength); $this->value = substr($this->rData, 2 + $this->tagLength); } @@ -77,7 +82,7 @@ public function getTagLength(): int * type:string, * flags:int, * tag:string, - * value:string, + * value: ?string, * } */ public function toArray(): array @@ -89,7 +94,7 @@ public function toArray(): array 'type' => $this->getType()->getName(), 'flags' => $this->getFlags(), 'tag' => $this->getTag(), - 'value' => $this->getValue(), + 'value' => $this->getValue() ]; } } diff --git a/src/ResourceRecord/RRTypes/CERT.php b/src/ResourceRecord/RRTypes/CERT.php index c7cb8bb..bd9bf84 100644 --- a/src/ResourceRecord/RRTypes/CERT.php +++ b/src/ResourceRecord/RRTypes/CERT.php @@ -4,9 +4,10 @@ namespace ArrayAccess\DnsRecord\ResourceRecord\RRTypes; use ArrayAccess\DnsRecord\Abstracts\AbstractResourceRecordType; -use function array_values; use function base64_encode; +use function is_array; use function substr; +use function unpack; /** * @@ -45,14 +46,18 @@ protected function parseRData(string $message, int $rdataOffset): void if ($this->rdLength < 6) { return; } + $data = unpack('nformat/nkeyTag/Calgorithm', $this->rData); + if (!is_array($data)) { + return; + } // // unpack the format, keytag and algorithm // [ - $this->format, - $this->keyTag, - $this->algorithm - ] = array_values(unpack('nformat/nkeytag/Calgorithm', $this->rData)); + 'format' => $this->format, + 'keyTag' => $this->keyTag, + 'algorithm' => $this->algorithm + ] = $data; // // copy the certificate diff --git a/src/ResourceRecord/RRTypes/DNSKEY.php b/src/ResourceRecord/RRTypes/DNSKEY.php index d44683b..4f7df02 100644 --- a/src/ResourceRecord/RRTypes/DNSKEY.php +++ b/src/ResourceRecord/RRTypes/DNSKEY.php @@ -5,6 +5,7 @@ use ArrayAccess\DnsRecord\Abstracts\AbstractResourceRecordType; use function base64_encode; +use function is_array; use function sprintf; use function unpack; @@ -74,13 +75,18 @@ class DNSKEY extends AbstractResourceRecordType */ protected function parseRData(string $message, int $rdataOffset): void { + $data = unpack("nflags/Cprotocol/Calgorithm/a*pubKey", $this->rData); + if (!is_array($data)) { + return; + } + [ 'flags' => $this->flags, // https://datatracker.ietf.org/doc/html/rfc4034#section-2.1.2 'protocol' => $this->protocol, 'algorithm' => $this->algorithm, 'pubKey' => $pubKey, - ] = unpack("nflags/Cprotocol/Calgorithm/a*pubKey", $this->rData); + ] = $data; // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 = 16 // convert binary flags $flags = sprintf("%016b\n", $this->flags); diff --git a/src/ResourceRecord/RRTypes/MG.php b/src/ResourceRecord/RRTypes/MG.php index 1967893..df48af9 100644 --- a/src/ResourceRecord/RRTypes/MG.php +++ b/src/ResourceRecord/RRTypes/MG.php @@ -8,7 +8,7 @@ /** * MG RDATA format (EXPERIMENTAL) - RFC1035 Section 3.3.6 - * MGMNAME A which specifies a mailbox which is a + * MGMNAME A which specifies a mailbox, which is a * member of the mail group specified by the domain name * * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ diff --git a/src/ResourceRecord/RRTypes/MR.php b/src/ResourceRecord/RRTypes/MR.php index ac22d21..4308f3f 100644 --- a/src/ResourceRecord/RRTypes/MR.php +++ b/src/ResourceRecord/RRTypes/MR.php @@ -9,7 +9,7 @@ /** * MR RDATA format (EXPERIMENTAL) - RFC1035 Section 3.3.8 * NEWNAME A which specifies a mailbox which is the - * proper rename of the specified mailbox. + * proper renamed of the specified mailbox. * * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * / NEWNAME / diff --git a/src/ResourceRecord/RRTypes/MX.php b/src/ResourceRecord/RRTypes/MX.php index 14bdc10..ddfb75a 100644 --- a/src/ResourceRecord/RRTypes/MX.php +++ b/src/ResourceRecord/RRTypes/MX.php @@ -5,6 +5,8 @@ use ArrayAccess\DnsRecord\Abstracts\AbstractResourceRecordType; use ArrayAccess\DnsRecord\Utils\Buffer; +use function is_array; +use function unpack; /** * MX RDATA format - RFC1035 Section 3.3.9 @@ -29,19 +31,23 @@ class MX extends AbstractResourceRecordType { const TYPE = 'MX'; - protected int $preference; + protected int $preference = -1; - protected string $exchange; + protected string $exchange = ''; /** * @inheritdoc */ protected function parseRData(string $message, int $rdataOffset): void { - ['preference' => $this->preference] = unpack( + $data = unpack( 'npreference', Buffer::read($message, $rdataOffset, 2) ); + if (!is_array($data)) { + return; + } + ['preference' => $this->preference] = $data; $this->exchange = Buffer::readLabel($message, $rdataOffset); $this->value = "$this->preference $this->exchange"; } diff --git a/src/ResourceRecord/RRTypes/OPT.php b/src/ResourceRecord/RRTypes/OPT.php index f3aa9e6..903768e 100644 --- a/src/ResourceRecord/RRTypes/OPT.php +++ b/src/ResourceRecord/RRTypes/OPT.php @@ -7,6 +7,7 @@ use ArrayAccess\DnsRecord\Interfaces\ResourceRecord\ResourceRecordMetaTypeInterface; use ArrayAccess\DnsRecord\Packet\Message; use ArrayAccess\DnsRecord\Utils\Lookup; +use function is_array; use function pack; use function unpack; @@ -93,18 +94,24 @@ public static function create( protected function parseRData(string $message, int $rdataOffset): void { - [ - 'extended' => $this->extended_rcode, - 'version' => $this->version, - 'do' => $do, - 'z' => $this->z, - ] = unpack('Cextended/Cversion/Cdo/Cz', pack('N', $this->ttl)); - $this->do = ($do >> 7); - if ($this->rdLength > 0) { + $data = unpack('Cextended/Cversion/Cdo/Cz', pack('N', $this->ttl)); + if (is_array($data)) { [ - 'option_code' => $this->option_code, - 'option_length' => $this->option_length - ] = unpack('noption_code/noption_length', $this->rData); + 'extended' => $this->extended_rcode, + 'version' => $this->version, + 'do' => $do, + 'z' => $this->z, + ] = $data; + $this->do = ($do >> 7); + } + if ($this->rdLength > 0) { + $data = unpack('noption_code/noption_length', $this->rData); + if (is_array($data)) { + [ + 'option_code' => $this->option_code, + 'option_length' => $this->option_length + ] = $data; + } $this->option_data = substr($this->rData, 4); } } diff --git a/src/ResourceRecord/RRTypes/RRSIG.php b/src/ResourceRecord/RRTypes/RRSIG.php index 389f166..c8ed938 100644 --- a/src/ResourceRecord/RRTypes/RRSIG.php +++ b/src/ResourceRecord/RRTypes/RRSIG.php @@ -6,6 +6,7 @@ use ArrayAccess\DnsRecord\Abstracts\AbstractResourceRecordType; use ArrayAccess\DnsRecord\Utils\Buffer; use function base64_encode; +use function is_array; use function strlen; use function unpack; @@ -37,18 +38,21 @@ class RRSIG extends AbstractResourceRecordType protected function parseRData(string $message, int $rdataOffset): void { $stuff = Buffer::read($message, $rdataOffset, 18); - [ - 'type' => $this->sigType, - 'algorithm' => $this->algorithm, - 'labels' => $this->labels, - 'originalttl' => $this->originalttl, - 'expiration' => $this->expiration, - 'inception' => $this->inception, - 'keytag' => $this->keyTag, - ] = unpack( + $stuff = unpack( "ntype/calgorithm/clabels/Noriginalttl/Nexpiration/Ninception/nkeytag", $stuff ); + if (is_array($stuff)) { + [ + 'type' => $this->sigType, + 'algorithm' => $this->algorithm, + 'labels' => $this->labels, + 'originalttl' => $this->originalttl, + 'expiration' => $this->expiration, + 'inception' => $this->inception, + 'keytag' => $this->keyTag, + ] = $stuff; + } $this->signer = Buffer::readLabel($message, $rdataOffset); $this->signature = base64_encode( Buffer::read($message, $rdataOffset, $this->rdLength - (strlen($this->signer) + 2) - 18) diff --git a/src/ResourceRecord/RRTypes/SOA.php b/src/ResourceRecord/RRTypes/SOA.php index f1a9bcc..85f92ad 100644 --- a/src/ResourceRecord/RRTypes/SOA.php +++ b/src/ResourceRecord/RRTypes/SOA.php @@ -5,6 +5,7 @@ use ArrayAccess\DnsRecord\Abstracts\AbstractResourceRecordType; use ArrayAccess\DnsRecord\Utils\Buffer; +use function is_array; use function sprintf; use function unpack; @@ -33,27 +34,30 @@ protected function parseRData($message, int $rdataOffset): void { $this->mName = Buffer::readLabel($message, $rdataOffset); $this->rName = Buffer::readLabel($message, $rdataOffset); - [ - 'serial' => $this->serial, - 'refresh' => $this->refresh, - 'retry' => $this->retry, - 'expire' => $this->expire, - 'minTTL' => $this->minimumTTL - ] = unpack( + $data = unpack( "Nserial/Nrefresh/Nretry/Nexpire/NminTTL", Buffer::read($message, $rdataOffset, 20) ); - - $this->value = sprintf( - '%s. %s. %d %d %d %d %d', - $this->mName, - $this->rName, - $this->serial, - $this->refresh, - $this->retry, - $this->expire, - $this->minimumTTL - ); + if (is_array($data)) { + [ + 'serial' => $this->serial, + 'refresh' => $this->refresh, + 'retry' => $this->retry, + 'expire' => $this->expire, + 'minTTL' => $this->minimumTTL + ] = $data; + + $this->value = sprintf( + '%s. %s. %d %d %d %d %d', + $this->mName, + $this->rName, + $this->serial, + $this->refresh, + $this->retry, + $this->expire, + $this->minimumTTL + ); + } } public function getMinimumTTL(): int diff --git a/src/ResourceRecord/RRTypes/SRV.php b/src/ResourceRecord/RRTypes/SRV.php index 36dfe87..4ad58d7 100644 --- a/src/ResourceRecord/RRTypes/SRV.php +++ b/src/ResourceRecord/RRTypes/SRV.php @@ -5,6 +5,7 @@ use ArrayAccess\DnsRecord\Abstracts\AbstractResourceRecordType; use ArrayAccess\DnsRecord\Utils\Buffer; +use function is_array; use function unpack; /** @@ -27,14 +28,17 @@ class SRV extends AbstractResourceRecordType protected function parseRData($message, int $rdataOffset): void { $offset = 0; - [ - 'priority' => $this->priority, - 'weight' => $this->weight, - 'port' => $this->port, - ] = unpack( + $data = unpack( 'npriority/nweight/nport', Buffer::read($this->rData, $offset, 6) ); + if (is_array($data)) { + [ + 'priority' => $this->priority, + 'weight' => $this->weight, + 'port' => $this->port, + ] = $data; + } $this->value = Buffer::readLabel($this->rData, $offset); } @@ -54,6 +58,17 @@ public function getPort(): int return $this->port; } + /** + * @return array{ + * host: string, + * class: string, + * type: string, + * pri: int, + * weight: int, + * port: int, + * target: ?string, + * } + */ public function toArray(): array { return [ diff --git a/src/ResourceRecord/RRTypes/TXT.php b/src/ResourceRecord/RRTypes/TXT.php index 00e8741..1f82ab7 100644 --- a/src/ResourceRecord/RRTypes/TXT.php +++ b/src/ResourceRecord/RRTypes/TXT.php @@ -14,7 +14,7 @@ * / TXT-DATA / * +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ * - * @use parent::parseRData() for logic + * @see AbstractResourceRecordType::parseRData() for logic * @link https://datatracker.ietf.org/doc/html/rfc1035#section-3.3.14 */ class TXT extends AbstractResourceRecordType diff --git a/src/Traits/DisableSetterTrait.php b/src/Traits/DisableSetterTrait.php index 52bfd2b..358835b 100644 --- a/src/Traits/DisableSetterTrait.php +++ b/src/Traits/DisableSetterTrait.php @@ -5,7 +5,7 @@ trait DisableSetterTrait { - final public function __set(string $name, $value): void + final public function __set(string $name, mixed $value): void { // pass } diff --git a/src/Traits/PacketSenderTrait.php b/src/Traits/PacketSenderTrait.php index 3616838..989c3a0 100644 --- a/src/Traits/PacketSenderTrait.php +++ b/src/Traits/PacketSenderTrait.php @@ -34,6 +34,9 @@ trait PacketSenderTrait { + /** + * @var array + */ private array $sockets = []; abstract public function getCache(): ?CacheStorageInterface; @@ -69,6 +72,7 @@ protected function setResourceTimeout($resource, int|float $timeout): void /** * @throws RequestException + * @return resource */ final protected function createSocketServer( bool $useUDP, @@ -111,7 +115,7 @@ final protected function createSocketServer( * @param bool $useUDP * @param string|null $server * @param int $port - * @param $serverList + * @param mixed $serverList * @return array{ * protocol: string, * server: string, @@ -125,7 +129,7 @@ final protected function createSocket( bool $useUDP, ?string $server = null, int $port = 53, - &$serverList = null + mixed &$serverList = null ) : array { if ($server) { $protocol = $useUDP ? "udp" : "tcp"; @@ -151,7 +155,7 @@ final protected function createSocket( sprintf( 'Can not connect to server "%s" last error : %s', $server, - ($e->getMessage()??null)?:'Unknown Error' + ($e->getMessage()?:null)?:'Unknown Error' ), $e->getCode() ); @@ -192,13 +196,14 @@ protected function sendCommand( set_error_handler(static function ($errCode, $errMsg) use (&$eCode, &$eMessage) { $eCode = $errCode; $eMessage = $errMsg; + return true; }); try { $status = fwrite($resource, $query); $info = stream_get_meta_data($resource); // $isUdp = $info['stream_type'] === 'udp_socket'; if ($status === false) { - $isTimeout = $info && !empty($info['timed_out']); + $isTimeout = !empty($info['timed_out']); $eMessage = $eMessage ?: ( $isTimeout ? 'Write process timed out' : 'Unknown error while writing data' ); @@ -226,7 +231,7 @@ protected function sendCommand( } if ($data === false) { - $isTimeout = $info && !empty($info['timed_out']); + $isTimeout = !empty($info['timed_out']); $eMessage = $eMessage ?: ( $isTimeout ? 'Read process timed out' : 'Unknown error while reading data' ); @@ -328,8 +333,11 @@ protected function sendTCP( private function saveResponseCache(PacketResponseInterface $response): void { + $cache = $this->getCache(); + if (!$cache) { // @phpstan-ignore-line + return; + } try { - $cache = $this->getCache(); $cacheTime = null; foreach ($response->getAnswers()->getRecords() as $type) { if (!$this->cacheAbleResource($type->getClass()->getName())) { @@ -353,18 +361,18 @@ private function saveResponseCache(PacketResponseInterface $response): void private function getCachePacket(PacketRequestDataInterface $packetRequestData): ?PacketResponseInterface { $cache = $this->getCache(); - if (!$cache) { + if (!$cache) { // @phpstan-ignore-line return null; } try { - if (($response = $this->getCache()->getItem($packetRequestData)) instanceof PacketResponseInterface) { + if (($response = $cache->getItem($packetRequestData)) instanceof PacketResponseInterface) { $currentTime = time(); $endTime = ($response->getEndTime() / 1000) + CacheStorageInterface::MAXIMUM_TTL; $shouldExpired = $endTime < $currentTime; if (!$shouldExpired) { return $response; } - $this->getCache()->deleteItem( + $cache->deleteItem( $response->getPacketData() ); } @@ -373,12 +381,12 @@ private function getCachePacket(PacketRequestDataInterface $packetRequestData): return null; } - /** + /* * @param string $protocol * @param string $server * @param string $port * @return void - */ + * unused private function closeSocket( string $protocol, string $server, @@ -391,8 +399,12 @@ private function closeSocket( fclose($this->sockets["$protocol://$server:$port"]); } unset($this->sockets["$protocol://$server:$port"]); - } + }*/ + /** + * @param resource $resource + * @return bool + */ private function closeSocketResource(&$resource): bool { if (!is_resource($resource)) { @@ -400,12 +412,11 @@ private function closeSocketResource(&$resource): bool } try { $meta = stream_get_meta_data($resource); - $uri = $meta['uri'] ?? null; + $uri = !empty($meta['uri']) ? $meta['uri'] : null; + fclose($resource); if (!$uri) { - fclose($resource); return true; } - fclose($resource); if (isset($this->sockets[$uri])) { unset($this->sockets[$uri]); } diff --git a/src/Utils/Addresses.php b/src/Utils/Addresses.php index 63efccb..84f0e51 100644 --- a/src/Utils/Addresses.php +++ b/src/Utils/Addresses.php @@ -187,6 +187,9 @@ public static function filterDomain(mixed $domainName): ?string if ($intl_idn) { $domainName = $isAscii ? idn_to_utf8($domainName) : idn_to_ascii($domainName); + if (!$domainName) { + return null; + } // revert $domainName = ($isAscii ? idn_to_ascii($domainName) : idn_to_utf8($domainName)) ?: null; if (!$domainName) { @@ -196,8 +199,12 @@ public static function filterDomain(mixed $domainName): ?string } else { foreach ($labels as &$label) { if (preg_match('/[^x00-x7F]/', $domainName)) { - $label = 'xn--' . self::punycodeEncode($label); - if (!$label || strlen($label) > 63) { + $encode = self::punycodeEncode($label); + if (!$encode) { + return null; + } + $label = 'xn--' . $encode; + if (strlen($label) > 63) { return null; } } @@ -365,14 +372,11 @@ private static function utf8Decode(string $input): array for ($i = 0; $i < $length; ++$i) { $byte = ord($input[$i]); - if (0 === $bytesNeeded) { - if ($byte >= 0x00 && $byte <= 0x7F) { + if ($byte >= 0x00 && $byte <= 0x7F) { // @phpstan-ignore-line $codePoints[] = $byte; - continue; } - if ($byte >= 0xC2 && $byte <= 0xDF) { $bytesNeeded = 1; $codePoint = $byte & 0x1F; diff --git a/src/Utils/Buffer.php b/src/Utils/Buffer.php index 01d3830..433a68c 100644 --- a/src/Utils/Buffer.php +++ b/src/Utils/Buffer.php @@ -5,11 +5,11 @@ namespace ArrayAccess\DnsRecord\Utils; use ArrayAccess\DnsRecord\Exceptions\EmptyArgumentException; +use ArrayAccess\DnsRecord\Interfaces\Packet\PacketHeaderInterface; use ArrayAccess\DnsRecord\Interfaces\Packet\PacketQuestionInterface; use ArrayAccess\DnsRecord\Interfaces\ResourceRecord\ResourceRecordClassInterface; use ArrayAccess\DnsRecord\Interfaces\ResourceRecord\ResourceRecordQTypeDefinitionInterface; use ArrayAccess\DnsRecord\Interfaces\ResourceRecord\ResourceRecordTypeInterface; -use ArrayAccess\DnsRecord\Packet\Header; use ArrayAccess\DnsRecord\ResourceRecord\RRTypes\OPT; use function chr; use function explode; @@ -88,11 +88,11 @@ public static function readLabel(string $buffer, int &$offset, string $delimiter * * @see Header * @link https://datatracker.ietf.org/doc/html/rfc5395#section-2 - * @param Header $header + * @param PacketHeaderInterface $header * * @return string */ - public static function createHeaderMessage(Header $header) : string + public static function createHeaderMessage(PacketHeaderInterface $header) : string { $message = pack('n', $header->getId()); $message .= chr( @@ -130,7 +130,7 @@ public static function createHeaderMessage(Header $header) : string public static function createQuestionMessage(PacketQuestionInterface $rr): string { $message = self::compressLabel($rr->getName()); - $message .= self::compressHeader($rr->getType(), $rr->getClass()); + $message .= self::compressHeader($rr->getType()??'', $rr->getClass()??''); return $message; } @@ -174,7 +174,7 @@ public static function compressLabel(string $name): string ); } - $name = preg_replace('~\\\+.~', '.', $name); + $name = (string) preg_replace('~\\\+.~', '.', $name); $computedName = ''; foreach (explode('.', $name) as $label) { if ($label === '') { diff --git a/src/Utils/Caller.php b/src/Utils/Caller.php index 2665fb7..be82c4f 100644 --- a/src/Utils/Caller.php +++ b/src/Utils/Caller.php @@ -14,13 +14,14 @@ class Caller */ public static function track( callable $callable, - &$errorCode = 0, - &$errorMessage = '', - &...$args - ) { + mixed &$errorCode = 0, + mixed &$errorMessage = '', + mixed &...$args + ) : mixed { set_error_handler(static function ($code, $message) use (&$errorCode, &$errorMessage) { $errorCode = $code; $errorMessage = $message; + return true; }); try { return $callable(...$args); @@ -39,9 +40,9 @@ public static function track( */ public static function call( callable $callable, - ...$args - ) { - set_error_handler(static fn () => null); + mixed ...$args + ) : mixed { + set_error_handler(static fn () => true); try { return $callable(...$args); } finally { diff --git a/src/Utils/Lookup.php b/src/Utils/Lookup.php index cc43148..5f968bf 100644 --- a/src/Utils/Lookup.php +++ b/src/Utils/Lookup.php @@ -90,6 +90,9 @@ class Lookup 'DSO' => self::OPCODE_DSO, ]; + /** + * @var class-string[]|ResourceRecordOpcodeInterface[] + */ private static array $opcodeCache = [ self::OPCODE_QUERY => Query::class, self::OPCODE_IQUERY => IQuery::class, diff --git a/tests/Cache/CacheStorageTest.php b/tests/Cache/CacheStorageTest.php index 93ff3c1..10f8244 100644 --- a/tests/Cache/CacheStorageTest.php +++ b/tests/Cache/CacheStorageTest.php @@ -41,8 +41,9 @@ private function createFakePacketRequestData() : PacketRequestDataInterface { return new class implements PacketRequestDataInterface { - public function serialize() + public function serialize() : ?string { + return null; } public function unserialize(string $data) @@ -100,11 +101,18 @@ public function createRequest(?CacheStorageInterface $cacheStorage = null): Pack return (new ReflectionClass(Request::class))->newInstanceWithoutConstructor(); } + /** + * @return array{} + */ public function __serialize(): array { return []; } + /** + * @param array{} $data + * @return void + */ public function __unserialize(array $data): void { } @@ -124,7 +132,7 @@ private function createFakeResponse(): Response ); } - public function testGetCacheName() + public function testGetCacheName() : void { $cacheName = $this->cacheStorage->getCacheName( $this->createFakePacketRequestData() @@ -151,7 +159,7 @@ public function testGetCacheName() ); } - public function testGetAdapter() + public function testGetAdapter() : void { /** * @see self::testSetAdapter() @@ -165,7 +173,7 @@ public function testGetAdapter() ); } - public function testSetAdapter() + public function testSetAdapter() : void { $cacheAdapter = new ArrayCacheAdapter(); /** @@ -173,7 +181,7 @@ public function testSetAdapter() * @noinspection PhpVoidFunctionResultUsedInspection */ $this->assertNull( - $this->cacheStorage->setAdapter($cacheAdapter), + $this->cacheStorage->setAdapter($cacheAdapter), // @phpstan-ignore-line sprintf( '%1$s->setAdapter(%2$s) should no return', $this->cacheStorageClassName, @@ -192,7 +200,7 @@ public function testSetAdapter() ); } - public function testSaveItem() + public function testSaveItem() : void { $fakeResponse = $this->createFakeResponse(); $this->assertFalse( @@ -215,7 +223,7 @@ public function testSaveItem() ); } - public function testGetItem() + public function testGetItem() : void { $key = 'nothing'; $this->assertNull( @@ -261,7 +269,7 @@ public function testGetItem() ); } - public function testDeleteItem() + public function testDeleteItem() : void { $key = 'nothing'; $this->assertFalse( @@ -287,7 +295,7 @@ public function testDeleteItem() ); } - public function testDeleteItems() + public function testDeleteItems() : void { $key = 'nothing'; $this->assertFalse( @@ -313,7 +321,7 @@ public function testDeleteItems() ); } - public function testHasItem() + public function testHasItem() : void { $fakeResponse = $this->createFakeResponse(); $this->assertFalse( diff --git a/tests/DnsServer/CustomDnsServerTest.php b/tests/DnsServer/CustomDnsServerTest.php index dd427f1..f298efd 100644 --- a/tests/DnsServer/CustomDnsServerTest.php +++ b/tests/DnsServer/CustomDnsServerTest.php @@ -7,11 +7,11 @@ use ArrayAccess\DnsRecord\Interfaces\DnsServer\DnsServerInterface; use PHPUnit\Framework\TestCase; use function sprintf; +use function unserialize; class CustomDnsServerTest extends TestCase { - - public function testConstruct() + public function testConstruct() : void { $this->assertInstanceOf( DnsServerInterface::class, @@ -24,7 +24,7 @@ public function testConstruct() ); } - public function testCreate() + public function testCreate() : void { $dns = '8.8.8.8'; $customDns = CustomDnsServer::create($dns); @@ -65,4 +65,45 @@ public function testCreate() ) ); } + + public function testSerializeUnserialize() : void + { + $customDns = CustomDnsServer::create('8.8.8.8', '8.8.4.4'); + $this->assertInstanceOf( + CustomDnsServer::class, + unserialize(serialize($customDns)), + sprintf( + 'unserialize(serialize(%1$s)) should restore object', + CustomDnsServer::class + ) + ); + + /** @noinspection PhpUnhandledExceptionInspection */ + $this->assertIsString( + $customDns->serialize(), + sprintf( + '%1$s->serialize() should serialized string', + CustomDnsServer::class + ) + ); + + /** @noinspection PhpUnhandledExceptionInspection */ + $this->assertSame( + [ + 'identity' => $customDns->getIdentity(), + 'name' => $customDns->getName(), + 'primaryServer' => $customDns->getPrimaryServer(), + 'secondaryServer' => $customDns->getSecondaryServer(), + 'port' => $customDns->getPort() + ], + unserialize($customDns->serialize()), + 'Checking unserialize value for consistency' + ); + /** @noinspection PhpUnhandledExceptionInspection */ + /** @noinspection PhpVoidFunctionResultUsedInspection */ + $this->assertNull( + $customDns->unserialize($customDns->serialize()), // @phpstan-ignore-line + '%1$s->unserialize(%1$s->serialize()) should no return' + ); + } } diff --git a/tests/DnsServerStorageTest.php b/tests/DnsServerStorageTest.php index e56aadc..bb41ce2 100644 --- a/tests/DnsServerStorageTest.php +++ b/tests/DnsServerStorageTest.php @@ -23,6 +23,9 @@ class DnsServerStorageTest extends TestCase { protected DnsServerStorage $dnsServerStorage; + /** + * @var class-string + */ protected string $dnsClassName; /** @@ -36,7 +39,7 @@ public function setUp(): void $this->dnsClassName = $this->dnsServerStorage::class; } - public function testObject() + public function testObject() : void { $google = new Google(); $this->assertContains( @@ -77,7 +80,7 @@ public function testObject() ); } - public function testGetServers() + public function testGetServers() : void { $this->assertNotEmpty( $this->dnsServerStorage->getServers(), @@ -88,7 +91,7 @@ public function testGetServers() ); } - public function testCount() + public function testCount() : void { $this->assertCount( count($this->dnsServerStorage->getServers()), @@ -100,7 +103,7 @@ public function testCount() ); } - public function testGetIterator() + public function testGetIterator() : void { $this->assertInstanceOf( ArrayIterator::class, @@ -132,7 +135,7 @@ public function testGetIterator() } } - public function testRemove() + public function testRemove() : void { $servers = $this->dnsServerStorage->getServers(); $total = count($servers); @@ -141,7 +144,7 @@ public function testRemove() * @noinspection PhpVoidFunctionResultUsedInspection */ $this->assertNull( - $this->dnsServerStorage->remove(reset($servers)), + $this->dnsServerStorage->remove(reset($servers)), // @phpstan-ignore-line sprintf( '%s->remove() should no return', $this->dnsClassName @@ -155,14 +158,25 @@ public function testRemove() $this->dnsClassName ) ); + $this->assertSame( + count($this->dnsServerStorage), + $this->dnsServerStorage->count(), + sprintf( + 'count(%1$s) should identical with %1$s->count()', + $this->dnsClassName + ) + ); } - public function testGet() + public function testGet() : void { $this->assertNull( $this->dnsServerStorage->get('not_exist_server'), 'Dns server identity "not_exist_server" should not exist' ); + /** + * @var Google $google + */ $google = $this->dnsServerStorage::getDefaultServer(Google::class); $this->assertSame( $this->dnsServerStorage->get($google->getIdentity()), @@ -185,7 +199,7 @@ public function testGet() ) ); $this->assertSame( - $this->dnsServerStorage->get($google)->getIdentity(), + $this->dnsServerStorage->get($google)?->getIdentity(), $google::class, sprintf( 'Method %1$s->get(%2$s)->getIdentity() should equal with id %3$s', @@ -196,7 +210,7 @@ public function testGet() ); } - public function testAdd() + public function testAdd() : void { $total = count($this->dnsServerStorage); @@ -206,7 +220,7 @@ public function testAdd() * @noinspection PhpVoidFunctionResultUsedInspection */ $this->assertNull( - $this->dnsServerStorage->add($custom), + $this->dnsServerStorage->add($custom), // @phpstan-ignore-line sprintf( '%1$s->add(%2$s) should no return', $this->dnsClassName, @@ -258,7 +272,7 @@ public function testAdd() ); } - public function testGetDefaultServer() + public function testGetDefaultServer() : void { $this->assertInstanceOf( Google::class, @@ -281,7 +295,7 @@ public function testGetDefaultServer() ); } - public function testCreateDefault() + public function testCreateDefault() : void { $this->assertInstanceOf( $this->dnsClassName, @@ -313,7 +327,7 @@ public function testCreateDefault() ); } - public function testSerialize() + public function testSerialize() : void { try { // just reduce error @@ -346,9 +360,26 @@ public function testSerialize() $this->dnsClassName ) ); + /** @noinspection PhpUnhandledExceptionInspection */ + $this->assertIsString( + $this->dnsServerStorage->serialize(), + sprintf( + '%1$s->serialize() should string', + $this->dnsClassName + ) + ); + /** @noinspection PhpUnhandledExceptionInspection */ + $this->assertArrayHasKey( + 'servers', + unserialize($this->dnsServerStorage->serialize()), + sprintf( + 'unserialize(%1$s->serialize()) should array has key "servers"', + $this->dnsClassName + ) + ); } - public function testUnserialize() + public function testUnserialize() : void { try { $object = unserialize(serialize($this->dnsServerStorage)); @@ -363,5 +394,16 @@ public function testUnserialize() $this->dnsClassName ) ); + /** @noinspection PhpVoidFunctionResultUsedInspection */ + /** @noinspection PhpUnhandledExceptionInspection */ + $this->assertNull( + $this->dnsServerStorage->unserialize( // @phpstan-ignore-line + $this->dnsServerStorage->serialize() + ), + sprintf( + '%1$s->unserialize(%1$s->serialize()) should no return', + $this->dnsClassName + ) + ); } } diff --git a/tests/Packet/HeaderTest.php b/tests/Packet/HeaderTest.php index dd41309..0040f06 100644 --- a/tests/Packet/HeaderTest.php +++ b/tests/Packet/HeaderTest.php @@ -16,7 +16,7 @@ class HeaderTest extends TestCase * * @see \Tests\ArrayAccess\DnsRecord\Utils\BufferTest::testCreateQuestionMessage() */ - public function testFromMessage() + public function testFromMessage() : void { try { Header::fromMessage(''); diff --git a/tests/Packet/MessageTest.php b/tests/Packet/MessageTest.php index dc17a7f..dd985c6 100644 --- a/tests/Packet/MessageTest.php +++ b/tests/Packet/MessageTest.php @@ -11,7 +11,7 @@ class MessageTest extends TestCase { - public function testToString() + public function testToString() : void { $message = md5(microtime()); $this->assertSame( @@ -25,7 +25,7 @@ public function testToString() ); } - public function testGetMessage() + public function testGetMessage() : void { $message = md5(microtime()); $this->assertSame( diff --git a/tests/ResolverTest.php b/tests/ResolverTest.php index ee8b628..bff9569 100644 --- a/tests/ResolverTest.php +++ b/tests/ResolverTest.php @@ -28,7 +28,7 @@ */ class ResolverTest extends TestCase { - public function testSetDnsServerStorage() + public function testSetDnsServerStorage() : void { $resolver = new Resolver(); $dnsServerStorage = $resolver->getDnsServerStorage(); @@ -43,7 +43,7 @@ public function testSetDnsServerStorage() ); } - public function testGetDnsServerStorage() + public function testGetDnsServerStorage() : void { $resolver = new Resolver(); $dnsServerStorage = $resolver->getDnsServerStorage(); @@ -67,7 +67,7 @@ public function testGetDnsServerStorage() ); } - public function testSetCache() + public function testSetCache() : void { $resolver = new Resolver(); $cache = $resolver->getCache(); @@ -82,7 +82,7 @@ public function testSetCache() ); } - public function testGetCache() + public function testGetCache() : void { $resolver = new Resolver(); $cache = $resolver->getCache(); @@ -123,7 +123,7 @@ public function testGetCache() ); } - public function testQuery() + public function testQuery() : void { $resolver = new Resolver(); $query = $resolver->query('example.com'); @@ -160,7 +160,7 @@ public function testQuery() ); } - public function testIQuery() + public function testIQuery() : void { $resolver = new Resolver(); $query = $resolver->iQuery('example.com'); @@ -184,7 +184,7 @@ public function testIQuery() ); } - public function testLookup() + public function testLookup() : void { $resolver = new Resolver( DnsServerStorage::createDefault(), @@ -223,7 +223,7 @@ public function testLookup() ); } - public function testLookups() + public function testLookups() : void { $resolver = new Resolver(); $lookups = $resolver->lookups( @@ -268,12 +268,12 @@ public function testLookups() ); $this->assertSame( 'example.com', - $lookups['A']->getAnswers()->getQuestion()->getName(), + $lookups['A']->getAnswers()->getQuestion()?->getName(), 'Question name lookup should example.com' ); $this->assertSame( IN::NAME, - $lookups['A']->getAnswers()->getQuestion()->getClass()->getName(), + $lookups['A']->getAnswers()->getQuestion()->getClass()?->getName(), sprintf( 'Question class name lookup should %s', IN::NAME @@ -326,12 +326,12 @@ public function testLookups() ); $this->assertSame( 'example.com', - $lookups['B']->getAnswers()->getQuestion()->getName(), + $lookups['B']->getAnswers()->getQuestion()?->getName(), 'Question name lookup should example.com' ); $this->assertSame( IN::NAME, - $lookups['B']->getAnswers()->getQuestion()->getClass()->getName(), + $lookups['B']->getAnswers()->getQuestion()->getClass()?->getName(), sprintf( 'Question class name lookup should %s', IN::NAME @@ -349,4 +349,45 @@ public function testLookups() ); } } + + public function testSetGetFlag() : void + { + $resolver = new Resolver(); + $this->assertFalse( + $resolver->isCdFlag(), + 'CDFlag default set to false' + ); + $this->assertTrue( + $resolver->isAdFlag(), + 'ADFlag default set to true' + ); + $this->assertFalse( + $resolver->isDnsSec(), + 'DNSSec default set to false' + ); + $this->assertTrue( + $resolver->isRecurse(), + 'Recurse default set to true' + ); + $resolver->setCdFlag(true); + $this->assertTrue( + $resolver->isCdFlag(), + 'CDFlag after set true' + ); + $resolver->setAdFlag(false); + $this->assertFalse( + $resolver->isAdFlag(), + 'CDFlag after set false' + ); + $resolver->setDnsSec(true); + $this->assertTrue( + $resolver->isDnsSec(), + 'DNSSec set false' + ); + $resolver->setRecurse(false); + $this->assertFalse( + $resolver->isRecurse(), + 'Recurse set false' + ); + } } diff --git a/tests/Utils/AddressesTest.php b/tests/Utils/AddressesTest.php index b0c9f32..5d88202 100644 --- a/tests/Utils/AddressesTest.php +++ b/tests/Utils/AddressesTest.php @@ -13,7 +13,7 @@ class AddressesTest extends TestCase { - public function testFilterDomain() + public function testFilterDomain() : void { $baseDomain = 'example.com'; // base domain $httpsDomainWithPort = "https://$baseDomain:443/"; @@ -99,7 +99,7 @@ public function testFilterDomain() ); } - public function testFilterIp() + public function testFilterIp() : void { $invalidIP = '127.0.0.'; $validLocalIP = '127.0.0.1'; @@ -156,7 +156,7 @@ public function testFilterIp() ); } - public function testFilterIpv4() + public function testFilterIpv4() : void { $invalidIP = '::1'; $validLocalIP = '127.0.0.1'; @@ -177,7 +177,7 @@ public function testFilterIpv4() ); } - public function testFilterIpv6() + public function testFilterIpv6() : void { $invalidIP = '127.0.0.1'; $validLocalIP = '::1'; @@ -198,7 +198,7 @@ public function testFilterIpv6() ); } - public function testReverseIp() + public function testReverseIp() : void { $invalidIP = '127.0.0.'; $invalidIPv6 = '::1:::'; @@ -246,7 +246,7 @@ public function testReverseIp() ); } - public function testGuessDNSServer() + public function testGuessDNSServer() : void { $invalidIP = '127.0.0.'; $validIP = '127.0.0.1'; diff --git a/tests/Utils/BufferTest.php b/tests/Utils/BufferTest.php index bad770b..504fc09 100644 --- a/tests/Utils/BufferTest.php +++ b/tests/Utils/BufferTest.php @@ -14,7 +14,7 @@ class BufferTest extends TestCase { - public function testRead() + public function testRead() : void { $printed = 'printed'; $skipped = '_skipped'; @@ -66,7 +66,7 @@ public function testRead() ); } - public function testCreateHeaderMessage() + public function testCreateHeaderMessage() : void { $header = Header::createQueryHeader(); $this->assertSame( @@ -79,7 +79,7 @@ public function testCreateHeaderMessage() ); } - public function testCompressLabel() + public function testCompressLabel() : void { $domain = 'example.com'; $label = Buffer::compressLabel($domain); @@ -94,7 +94,7 @@ public function testCompressLabel() ); } - public function testReadLabel() + public function testReadLabel() : void { $offset = 0; $domain = 'example.com'; @@ -171,7 +171,7 @@ public function testReadLabel() ); } - public function testCompressHeader() + public function testCompressHeader() : void { $header = Buffer::compressHeader( 'A', @@ -187,16 +187,19 @@ public function testCompressHeader() ); } - public function testCreateQuestionMessage() + public function testCreateQuestionMessage() : void { $question = Question::fromFilteredResponse( 'example.com', Lookup::RR_TYPES['A'], Lookup::QCLASS_IN ); + /** + * @var non-empty-string $header + */ $header = Buffer::compressHeader( - $question->getType(), - $question->getClass() + $question->getType(), // @phpstan-ignore-line + $question->getClass() // @phpstan-ignore-line ); $message = Buffer::createQuestionMessage($question); // header is on the end of binary string diff --git a/tests/Utils/CallerTest.php b/tests/Utils/CallerTest.php index 9442763..489cbdd 100644 --- a/tests/Utils/CallerTest.php +++ b/tests/Utils/CallerTest.php @@ -18,7 +18,7 @@ class CallerTest extends TestCase { #[WithoutErrorHandler] - public function testCall() + public function testCall() : void { $message = 'sample: '.md5(microtime()); $code = rand(0, 10); @@ -56,7 +56,7 @@ public function testCall() } #[WithoutErrorHandler] - public function testTrack() + public function testTrack() : void { $message = 'Message 1'; @trigger_error($message, E_USER_WARNING); diff --git a/tests/Utils/LookupTest.php b/tests/Utils/LookupTest.php index 7e49d2a..b5b5084 100644 --- a/tests/Utils/LookupTest.php +++ b/tests/Utils/LookupTest.php @@ -28,7 +28,7 @@ class LookupTest extends TestCase { - public function testResourceClass() + public function testResourceClass() : void { $exception = null; try { @@ -81,7 +81,7 @@ public function testResourceClass() ); } - public function testResourceOpcode() + public function testResourceOpcode() : void { $exception = null; try { @@ -177,7 +177,7 @@ public function testResourceOpcode() ); } - public function testResourceType() + public function testResourceType() : void { $exception = null; try { @@ -230,7 +230,7 @@ public function testResourceType() ); } - public function testSocket() + public function testSocket() : void { /* * protocol:string, server:string, port:int, socket: resource