diff --git a/composer.json b/composer.json index b08390d..f24554a 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,8 @@ } }, "require": { - "php": "^8.0" + "php": "^8.0", + "symfony/deprecation-contracts": "^2.1" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "*", diff --git a/src/Bencode.php b/src/Bencode.php index 93a5836..0ebe244 100644 --- a/src/Bencode.php +++ b/src/Bencode.php @@ -30,18 +30,43 @@ public static function encode(mixed $data): string * Decode bencoded data from string * * @param string $bencoded - * @param array $options + * @param array $options @deprecated * @param string|callable $listType Type declaration for lists - * @param string|callable $dictionaryType Type declaration for dictionaries + * @param string|callable $dictType Type declaration for dictionaries + * @param string|callable|null $dictionaryType Type declaration for dictionaries @deprecated * @return mixed */ public static function decode( string $bencoded, array $options = [], string|callable $listType = 'array', - string|callable $dictionaryType = 'array', + string|callable $dictType = 'array', + string|callable|null $dictionaryType = null, ): mixed { - $options = array_merge(compact('listType', 'dictionaryType'), $options); + // resolve dictType / dictionaryType alias + if (isset($dictionaryType)) { + trigger_deprecation( + 'sandfoxme/bencode', + '2.3.0', + 'dictionaryType option is deprecated, use dictType instead', + ); + $dictType = $dictionaryType; + } + + if (count($options) > 0) { + trigger_deprecation( + 'sandfoxme/bencode', + '2.1.0', + 'Using options array is deprecated, use named function parameters instead', + ); + + if (isset($options['dictionaryType'])) { + $options['dictType'] ??= $options['dictionaryType']; + unset($options['dictionaryType']); + } + } + + $options = array_merge(compact('listType', 'dictType'), $options); return (new Decoder($bencoded, ...$options))->decode(); } @@ -62,17 +87,19 @@ public static function dump(string $filename, mixed $data): bool * Load data from bencoded file * * @param string $filename - * @param array $options + * @param array $options @deprecated * @param string|callable $listType Type declaration for lists - * @param string|callable $dictionaryType Type declaration for dictionaries + * @param string|callable $dictType Type declaration for dictionaries + * @param string|callable|null $dictionaryType Type declaration for dictionaries @deprecated * @return mixed */ public static function load( string $filename, array $options = [], string|callable $listType = 'array', - string|callable $dictionaryType = 'array', + string|callable $dictType = 'array', + string|callable|null $dictionaryType = null, ): mixed { - return self::decode(file_get_contents($filename), $options, $listType, $dictionaryType); + return self::decode(file_get_contents($filename), $options, $listType, $dictType, $dictionaryType); } } diff --git a/src/Engine/Decoder.php b/src/Engine/Decoder.php index d134d36..ca3b754 100644 --- a/src/Engine/Decoder.php +++ b/src/Engine/Decoder.php @@ -34,9 +34,9 @@ final class Decoder public function __construct( private string $bencoded, string|callable $listType = 'array', - string|callable $dictionaryType = 'array', + string|callable $dictType = 'array', ) { - $this->options = compact('listType', 'dictionaryType'); + $this->options = compact('listType', 'dictType'); } public function decode(): mixed @@ -194,7 +194,7 @@ private function finalizeDict(): void $prevKey = $dictKey; } - $value = $this->convertArrayToType($dict, 'dictionaryType'); + $value = $this->convertArrayToType($dict, 'dictType'); $this->pop($value); } diff --git a/tests/DecodeDictTest.php b/tests/DecodeDictTest.php index 3d3c938..fa962f9 100644 --- a/tests/DecodeDictTest.php +++ b/tests/DecodeDictTest.php @@ -77,28 +77,28 @@ public function testListTypes() $encoded = 'd2:k1i2e2:k22:s12:k3i3e2:k42:s22:k5i5ee'; // array - $decodedArray = Bencode::decode($encoded, dictionaryType: 'array'); + $decodedArray = Bencode::decode($encoded, dictType: 'array'); $this->assertTrue(is_array($decodedArray)); $this->assertEquals($dict, $decodedArray); // stdClass $object = (object)$dict; - $decodedObject = Bencode::decode($encoded, dictionaryType: 'object'); + $decodedObject = Bencode::decode($encoded, dictType: 'object'); $this->assertEquals(stdClass::class, get_class($decodedObject)); $this->assertEquals($object, $decodedObject); // custom class $arrayObject = new ArrayObject($dict); - $decodedAO = Bencode::decode($encoded, dictionaryType: ArrayObject::class); + $decodedAO = Bencode::decode($encoded, dictType: ArrayObject::class); $this->assertEquals(ArrayObject::class, get_class($decodedAO)); $this->assertEquals($arrayObject, $decodedAO); // callback // use same array object as above - $decodedCallback = Bencode::decode($encoded, dictionaryType: function ($array) use ($dict) { + $decodedCallback = Bencode::decode($encoded, dictType: function ($array) use ($dict) { $this->assertEquals($dict, $array); // check thar array is passed here // you can pass extra parameter to the constructor for example diff --git a/tests/DecodeLegacyOptionsTest.php b/tests/DecodeLegacyOptionsTest.php index c225d37..1773405 100644 --- a/tests/DecodeLegacyOptionsTest.php +++ b/tests/DecodeLegacyOptionsTest.php @@ -23,4 +23,22 @@ public function testLegacyOptionsArray() $this->assertInstanceOf(ArrayObject::class, $decoded->list); $this->assertInstanceOf(stdClass::class, $decoded->dict); } + + public function testLegacyDictOption() + { + $dict = [ + 'k1' => 2, + 'k2' => 's1', + 'k3' => 3, + 'k4' => 's2', + 'k5' => 5, + ]; + $encoded = 'd2:k1i2e2:k22:s12:k3i3e2:k42:s22:k5i5ee'; + + $object = (object)$dict; + $decodedObject = Bencode::decode($encoded, dictionaryType: 'object'); + + $this->assertEquals(stdClass::class, get_class($decodedObject)); + $this->assertEquals($object, $decodedObject); + } }