From 1c764e86bd6c2f93eb9eb0aa2456dc162e77cd0f Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Fri, 11 Jan 2013 14:37:01 +0100 Subject: [PATCH 01/70] Fixed phpdoc --- PHP/BitTorrent/Decoder.php | 12 ++++++------ PHP/BitTorrent/Encoder.php | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/PHP/BitTorrent/Decoder.php b/PHP/BitTorrent/Decoder.php index 25bf67a..8dbabf6 100644 --- a/PHP/BitTorrent/Decoder.php +++ b/PHP/BitTorrent/Decoder.php @@ -40,7 +40,7 @@ public function __construct(EncoderInterface $encoder = null) { } /** - * {@inheritDoc} + * {@inheritdoc} */ public function decodeFile($file, $strict = false) { if (!is_readable($file)) { @@ -61,7 +61,7 @@ public function decodeFile($file, $strict = false) { } /** - * {@inheritDoc} + * {@inheritdoc} */ public function decode($string) { if ($string[0] === 'i') { @@ -78,7 +78,7 @@ public function decode($string) { } /** - * {@inheritDoc} + * {@inheritdoc} */ public function decodeInteger($integer) { if ($integer[0] !== 'i' || (!$ePos = strpos($integer, 'e'))) { @@ -100,7 +100,7 @@ public function decodeInteger($integer) { } /** - * {@inheritDoc} + * {@inheritdoc} */ public function decodeString($string) { $stringParts = explode(':', $string, 2); @@ -121,7 +121,7 @@ public function decodeString($string) { } /** - * {@inheritDoc} + * {@inheritdoc} */ public function decodeList($list) { if ($list[0] !== 'l') { @@ -148,7 +148,7 @@ public function decodeList($list) { } /** - * {@inheritDoc} + * {@inheritdoc} */ public function decodeDictionary($dictionary) { if ($dictionary[0] !== 'd') { diff --git a/PHP/BitTorrent/Encoder.php b/PHP/BitTorrent/Encoder.php index f6649c0..e000db7 100644 --- a/PHP/BitTorrent/Encoder.php +++ b/PHP/BitTorrent/Encoder.php @@ -39,7 +39,7 @@ public function __construct(array $params = array()) { } /** - * {@inheritDoc} + * {@inheritdoc} */ public function setParam($key, $value) { $this->params[$key] = $value; @@ -48,7 +48,7 @@ public function setParam($key, $value) { } /** - * {@inheritDoc} + * {@inheritdoc} */ public function encode($var) { if ($this->isInt($var)) { @@ -75,7 +75,7 @@ public function encode($var) { } /** - * {@inheritDoc} + * {@inheritdoc} */ public function encodeInteger($integer) { if ($this->isInt($integer)) { @@ -86,7 +86,7 @@ public function encodeInteger($integer) { } /** - * {@inheritDoc} + * {@inheritdoc} */ public function encodeString($string) { if (!is_string($string)) { @@ -97,7 +97,7 @@ public function encodeString($string) { } /** - * {@inheritDoc} + * {@inheritdoc} */ public function encodeList($list) { if (!is_array($list)) { @@ -114,7 +114,7 @@ public function encodeList($list) { } /** - * {@inheritDoc} + * {@inheritdoc} */ public function encodeDictionary($dictionary) { if (!is_array($dictionary)) { From a685cc152d44b825a74578ee82b8adcc7dfec6ac Mon Sep 17 00:00:00 2001 From: StormWalkerEc Date: Wed, 15 Oct 2014 12:26:59 -0500 Subject: [PATCH 02/70] Private Tag in Torrent Returns if the torrent is private or not --- PHP/BitTorrent/Torrent.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/PHP/BitTorrent/Torrent.php b/PHP/BitTorrent/Torrent.php index 05f4ac0..2a1bb7e 100644 --- a/PHP/BitTorrent/Torrent.php +++ b/PHP/BitTorrent/Torrent.php @@ -656,6 +656,18 @@ private function getInfoPart() { return $info; } + + /** + * Get the private tag in the torrent + * + * + * @return boolean + */ + public function getPrivateFlag() { + $info = $this->getInfoPart(); + + return $info['private']; + } /** * Add method that should work on both 32 and 64-bit platforms From bf941ee80c024299ad634fc3caa0e1e17feca0ac Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Fri, 31 Oct 2014 17:27:05 +0100 Subject: [PATCH 03/70] Updated PHPUnit version dependency --- composer.json | 2 +- composer.lock | 210 +++++++++++++++++++++++++++----------------------- 2 files changed, 114 insertions(+), 98 deletions(-) diff --git a/composer.json b/composer.json index 35bf034..d936ba3 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "php": ">=5.3.2" }, "require-dev": { - "phpunit/phpunit": "3.7.*" + "phpunit/phpunit": "~3.7" }, "support": { "issues": "https://github.com/christeredvartsen/php-bittorrent/issues" diff --git a/composer.lock b/composer.lock index 19c2696..36c002a 100644 --- a/composer.lock +++ b/composer.lock @@ -1,36 +1,45 @@ { - "hash": "5466fe3d7335b0d1fb70ab282a0bddb7", - "packages": [ - + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" ], + "hash": "d4c5831d3da5ed2f09faabe1130bd05e", + "packages": [], "packages-dev": [ { "name": "phpunit/php-code-coverage", - "version": "1.2.7", + "version": "1.2.18", "source": { "type": "git", - "url": "git://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "1.2.7" + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b" }, "dist": { "type": "zip", - "url": "https://github.com/sebastianbergmann/php-code-coverage/archive/1.2.7.zip", - "reference": "1.2.7", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", + "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", "shasum": "" }, "require": { "php": ">=5.3.3", "phpunit/php-file-iterator": ">=1.3.0@stable", - "phpunit/php-token-stream": ">=1.1.3@stable", - "phpunit/php-text-template": ">=1.1.1@stable" + "phpunit/php-text-template": ">=1.2.0@stable", + "phpunit/php-token-stream": ">=1.1.3,<1.3.0" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*@dev" }, "suggest": { "ext-dom": "*", "ext-xdebug": ">=2.0.5" }, - "time": "2012-12-02 14:54:55", "type": "library", - "installation-source": "dist", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, "autoload": { "classmap": [ "PHP/" @@ -53,31 +62,30 @@ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ - "testing", "coverage", + "testing", "xunit" - ] + ], + "time": "2014-09-02 10:13:14" }, { "name": "phpunit/php-file-iterator", - "version": "1.3.3", + "version": "1.3.4", "source": { "type": "git", - "url": "git://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "1.3.3" + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" }, "dist": { "type": "zip", - "url": "https://github.com/sebastianbergmann/php-file-iterator/zipball/1.3.3", - "reference": "1.3.3", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", + "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "time": "2012-10-11 04:44:38", "type": "library", - "installation-source": "dist", "autoload": { "classmap": [ "File/" @@ -98,32 +106,31 @@ } ], "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "http://www.phpunit.de/", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "keywords": [ "filesystem", "iterator" - ] + ], + "time": "2013-10-10 15:34:57" }, { "name": "phpunit/php-text-template", - "version": "1.1.4", + "version": "1.2.0", "source": { "type": "git", - "url": "git://github.com/sebastianbergmann/php-text-template.git", - "reference": "1.1.4" + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" }, "dist": { "type": "zip", - "url": "https://github.com/sebastianbergmann/php-text-template/zipball/1.1.4", - "reference": "1.1.4", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "time": "2012-10-31 11:15:28", "type": "library", - "installation-source": "dist", "autoload": { "classmap": [ "Text/" @@ -147,28 +154,27 @@ "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ "template" - ] + ], + "time": "2014-01-30 17:20:04" }, { "name": "phpunit/php-timer", - "version": "1.0.4", + "version": "1.0.5", "source": { "type": "git", - "url": "git://github.com/sebastianbergmann/php-timer.git", - "reference": "1.0.4" + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" }, "dist": { "type": "zip", - "url": "https://github.com/sebastianbergmann/php-timer/zipball/1.0.4", - "reference": "1.0.4", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "time": "2012-10-11 04:45:58", "type": "library", - "installation-source": "dist", "autoload": { "classmap": [ "PHP/" @@ -189,32 +195,36 @@ } ], "description": "Utility class for timing", - "homepage": "http://www.phpunit.de/", + "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ "timer" - ] + ], + "time": "2013-08-02 07:42:54" }, { "name": "phpunit/php-token-stream", - "version": "1.1.5", + "version": "1.2.2", "source": { "type": "git", - "url": "git://github.com/sebastianbergmann/php-token-stream.git", - "reference": "1.1.5" + "url": "https://github.com/sebastianbergmann/php-token-stream.git", + "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32" }, "dist": { "type": "zip", - "url": "https://github.com/sebastianbergmann/php-token-stream/zipball/1.1.5", - "reference": "1.1.5", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32", + "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32", "shasum": "" }, "require": { "ext-tokenizer": "*", "php": ">=5.3.3" }, - "time": "2012-10-11 04:47:14", "type": "library", - "installation-source": "dist", + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" + } + }, "autoload": { "classmap": [ "PHP/" @@ -235,45 +245,47 @@ } ], "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "http://www.phpunit.de/", + "homepage": "https://github.com/sebastianbergmann/php-token-stream/", "keywords": [ "tokenizer" - ] + ], + "time": "2014-03-03 05:10:30" }, { "name": "phpunit/phpunit", - "version": "3.7.10", + "version": "3.7.38", "source": { "type": "git", - "url": "git://github.com/sebastianbergmann/phpunit.git", - "reference": "3.7.10" + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6" }, "dist": { "type": "zip", - "url": "https://github.com/sebastianbergmann/phpunit/archive/3.7.10.zip", - "reference": "3.7.10", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/38709dc22d519a3d1be46849868aa2ddf822bcf6", + "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6", "shasum": "" }, "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": ">=1.3.1", - "phpunit/php-text-template": ">=1.1.1", - "phpunit/php-code-coverage": ">=1.2.1", - "phpunit/php-timer": ">=1.0.2", - "phpunit/phpunit-mock-objects": ">=1.2.0,<1.3.0", - "symfony/yaml": ">=2.1.0", + "ext-ctype": "*", "ext-dom": "*", + "ext-json": "*", "ext-pcre": "*", "ext-reflection": "*", - "ext-spl": "*" + "ext-spl": "*", + "php": ">=5.3.3", + "phpunit/php-code-coverage": "~1.2", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.1", + "phpunit/php-timer": "~1.0", + "phpunit/phpunit-mock-objects": "~1.2", + "symfony/yaml": "~2.0" + }, + "require-dev": { + "pear-pear.php.net/pear": "1.9.4" }, "suggest": { - "phpunit/php-invoker": ">=1.1.0", - "ext-json": "*", - "ext-simplexml": "*", - "ext-tokenizer": "*" + "phpunit/php-invoker": "~1.1" }, - "time": "2012-12-02 14:56:55", "bin": [ "composer/bin/phpunit" ], @@ -283,7 +295,6 @@ "dev-master": "3.7.x-dev" } }, - "installation-source": "dist", "autoload": { "classmap": [ "PHPUnit/" @@ -307,23 +318,24 @@ "description": "The PHP Unit Testing framework.", "homepage": "http://www.phpunit.de/", "keywords": [ - "testing", "phpunit", + "testing", "xunit" - ] + ], + "time": "2014-10-17 09:04:17" }, { "name": "phpunit/phpunit-mock-objects", - "version": "1.2.2", + "version": "1.2.3", "source": { "type": "git", - "url": "git://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "1.2.2" + "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", + "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875" }, "dist": { "type": "zip", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects/archive/1.2.2.zip", - "reference": "1.2.2", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5794e3c5c5ba0fb037b11d8151add2a07fa82875", + "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875", "shasum": "" }, "require": { @@ -333,9 +345,7 @@ "suggest": { "ext-soap": "*" }, - "time": "2012-11-05 10:39:13", "type": "library", - "installation-source": "dist", "autoload": { "classmap": [ "PHPUnit/" @@ -360,32 +370,36 @@ "keywords": [ "mock", "xunit" - ] + ], + "time": "2013-01-13 10:24:48" }, { "name": "symfony/yaml", - "version": "v2.1.6", + "version": "v2.5.6", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", - "url": "https://github.com/symfony/Yaml", - "reference": "v2.1.6" + "url": "https://github.com/symfony/Yaml.git", + "reference": "2d9f527449cabfa8543dd7fa3a466d6ae83d6726" }, "dist": { "type": "zip", - "url": "https://github.com/symfony/Yaml/archive/v2.1.6.zip", - "reference": "v2.1.6", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/2d9f527449cabfa8543dd7fa3a466d6ae83d6726", + "reference": "2d9f527449cabfa8543dd7fa3a466d6ae83d6726", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "time": "2012-12-06 10:00:55", "type": "library", - "installation-source": "dist", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, "autoload": { "psr-0": { - "Symfony\\Component\\Yaml": "" + "Symfony\\Component\\Yaml\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -393,24 +407,26 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, { "name": "Symfony Community", "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], "description": "Symfony Yaml Component", - "homepage": "http://symfony.com" + "homepage": "http://symfony.com", + "time": "2014-10-01 05:50:18" } ], - "aliases": [ - - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": [ - - ] + "stability-flags": [], + "prefer-stable": false, + "platform": { + "php": ">=5.3.2" + }, + "platform-dev": [] } From 0686826dafe207b2f45975831234035cf4693fd6 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Fri, 31 Oct 2014 17:27:34 +0100 Subject: [PATCH 04/70] Renamed the name of the method fetching the optional private flag --- PHP/BitTorrent/Torrent.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/PHP/BitTorrent/Torrent.php b/PHP/BitTorrent/Torrent.php index 2a1bb7e..d7ae944 100644 --- a/PHP/BitTorrent/Torrent.php +++ b/PHP/BitTorrent/Torrent.php @@ -656,17 +656,16 @@ private function getInfoPart() { return $info; } - + /** - * Get the private tag in the torrent - * + * Check if the torrent is private or not (via the optional private flag) * * @return boolean */ - public function getPrivateFlag() { + public function isPrivate() { $info = $this->getInfoPart(); - return $info['private']; + return (isset($info['private']) && $info['private'] === 1) ? true : false; } /** From d6fd3172f0c69e58b9740a2f3a53df4a919dbd33 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Fri, 31 Oct 2014 17:28:19 +0100 Subject: [PATCH 05/70] Added two more test files --- tests/PHP/BitTorrent/_files/file_with_private_set_to_0.torrent | 1 + tests/PHP/BitTorrent/_files/file_with_private_set_to_1.torrent | 1 + 2 files changed, 2 insertions(+) create mode 100644 tests/PHP/BitTorrent/_files/file_with_private_set_to_0.torrent create mode 100644 tests/PHP/BitTorrent/_files/file_with_private_set_to_1.torrent diff --git a/tests/PHP/BitTorrent/_files/file_with_private_set_to_0.torrent b/tests/PHP/BitTorrent/_files/file_with_private_set_to_0.torrent new file mode 100644 index 0000000..7202bb0 --- /dev/null +++ b/tests/PHP/BitTorrent/_files/file_with_private_set_to_0.torrent @@ -0,0 +1 @@ +d8:announce17:http://trackerurl7:comment17:This is a comment13:creation datei1323713688e4:infod7:privatei0e5:filesld6:lengthi6939e4:pathl10:BitTorrent11:Decoder.phpeed6:lengthi4276e4:pathl10:BitTorrent11:Encoder.phpeed6:lengthi1777e4:pathl10:BitTorrent13:Exception.phpeed6:lengthi1803e4:pathl10:BitTorrent7:Torrent13:Exception.phpeed6:lengthi15448e4:pathl10:BitTorrent11:Torrent.phpeee4:name3:PHP12:piece lengthi262144e6:pieces20:CoFr*oDu\ee diff --git a/tests/PHP/BitTorrent/_files/file_with_private_set_to_1.torrent b/tests/PHP/BitTorrent/_files/file_with_private_set_to_1.torrent new file mode 100644 index 0000000..f699104 --- /dev/null +++ b/tests/PHP/BitTorrent/_files/file_with_private_set_to_1.torrent @@ -0,0 +1 @@ +d8:announce17:http://trackerurl7:comment17:This is a comment13:creation datei1323713688e4:infod7:privatei1e5:filesld6:lengthi6939e4:pathl10:BitTorrent11:Decoder.phpeed6:lengthi4276e4:pathl10:BitTorrent11:Encoder.phpeed6:lengthi1777e4:pathl10:BitTorrent13:Exception.phpeed6:lengthi1803e4:pathl10:BitTorrent7:Torrent13:Exception.phpeed6:lengthi15448e4:pathl10:BitTorrent11:Torrent.phpeee4:name3:PHP12:piece lengthi262144e6:pieces20:CoFr*oDu\ee From 8ab4488ac0bb738aeb19403f19dd5b73f3dd581b Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Fri, 31 Oct 2014 17:30:13 +0100 Subject: [PATCH 06/70] Updated values for some tests that was outdated when new test files were added --- tests/PHP/BitTorrent/TorrentTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/PHP/BitTorrent/TorrentTest.php b/tests/PHP/BitTorrent/TorrentTest.php index 517897e..a34958d 100644 --- a/tests/PHP/BitTorrent/TorrentTest.php +++ b/tests/PHP/BitTorrent/TorrentTest.php @@ -281,8 +281,8 @@ public function testCreateFromPathWhenUsingADirectoryAsArgument() { $this->assertSame($trackerUrl, $torrent->getAnnounce()); $this->assertSame('_files', $torrent->getName()); - $this->assertEquals(902004, $torrent->getSize()); - $this->assertSame(5, count($torrent->getFileList())); + $this->assertEquals(902910, $torrent->getSize()); + $this->assertSame(7, count($torrent->getFileList())); } /** @@ -346,8 +346,8 @@ public function testSaveTorrent() { $this->assertSame($comment, $torrent->getComment()); $this->assertSame($createdBy, $torrent->getCreatedBy()); $this->assertSame('_files', $torrent->getName()); - $this->assertEquals(902004, $torrent->getSize()); - $this->assertSame(5, count($torrent->getFileList())); + $this->assertEquals(902910, $torrent->getSize()); + $this->assertSame(7, count($torrent->getFileList())); $this->assertSame($announceList, $torrent->getAnnounceList()); // Remove the saved file From 2aa9cff8fa0bc1fbcff24a54e8e9207283609e56 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Fri, 31 Oct 2014 17:32:20 +0100 Subject: [PATCH 07/70] Updated ChangeLog --- ChangeLog.markdown | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ChangeLog.markdown b/ChangeLog.markdown index b9976cb..8f3165f 100644 --- a/ChangeLog.markdown +++ b/ChangeLog.markdown @@ -1,6 +1,12 @@ Changelog for PHP BitTorrent ===================== +Version 1.2.0 +------------- +__N/A__ + +* Added method to check if the torrent is private (@stormwalkerec) + Version 1.1.0 ------------- __2013-01-11__ From 6dba338a7a61e164fe64dc5d12ee6ebb3e60881e Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Fri, 31 Oct 2014 17:30:41 +0100 Subject: [PATCH 08/70] Added test cases for the isPrivate method --- tests/PHP/BitTorrent/TorrentTest.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/PHP/BitTorrent/TorrentTest.php b/tests/PHP/BitTorrent/TorrentTest.php index a34958d..9e22153 100644 --- a/tests/PHP/BitTorrent/TorrentTest.php +++ b/tests/PHP/BitTorrent/TorrentTest.php @@ -522,4 +522,31 @@ public function testGetSizeWithLargeValues() { $this->assertEquals("6442450944", $torrent1->getSize()); $this->assertEquals("5368709120", $torrent2->getSize()); } + + /** + * @covers PHP\BitTorrent\Torrent::isPrivate + */ + public function testIsPrivateWhenFlagDoesNotExist() { + $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/large_files.torrent'); + + $this->assertFalse($torrent->isPrivate()); + } + + /** + * @covers PHP\BitTorrent\Torrent::isPrivate + */ + public function testIsPrivateWhenItExistsAndIs1() { + $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/file_with_private_set_to_1.torrent'); + + $this->assertTrue($torrent->isPrivate()); + } + + /** + * @covers PHP\BitTorrent\Torrent::isPrivate + */ + public function testIsPrivateWhenItExistsAndIsNot1() { + $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/file_with_private_set_to_0.torrent'); + + $this->assertFalse($torrent->isPrivate()); + } } From 5b4e66a92f113fb403457ee0aea3d40f4e8e52c2 Mon Sep 17 00:00:00 2001 From: Vedmant Date: Tue, 11 Jul 2017 10:26:48 +0300 Subject: [PATCH 09/70] Allow trackerless torrents - announce is not required --- PHP/BitTorrent/Torrent.php | 11 ++++------- tests/PHP/BitTorrent/TorrentTest.php | 14 -------------- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/PHP/BitTorrent/Torrent.php b/PHP/BitTorrent/Torrent.php index d7ae944..698be81 100644 --- a/PHP/BitTorrent/Torrent.php +++ b/PHP/BitTorrent/Torrent.php @@ -506,12 +506,6 @@ public function save($filename, EncoderInterface $encoder = null) { throw new InvalidArgumentException('Could not open file "' . $filename . '" for writing.'); } - $announce = $this->getAnnounce(); - - if (empty($announce)) { - throw new RuntimeException('Announce URL is missing.'); - } - $info = $this->getInfoPart(); if ($encoder === null) { @@ -525,11 +519,14 @@ public function save($filename, EncoderInterface $encoder = null) { } $torrent = array( - 'announce' => $announce, 'creation date' => $createdAt, 'info' => $info, ); + if (($announce = $this->getAnnounce()) !== null) { + $torrent['announce'] = $announce; + } + if (($announceList = $this->getAnnounceList()) !== null) { $torrent['announce-list'] = $announceList; } diff --git a/tests/PHP/BitTorrent/TorrentTest.php b/tests/PHP/BitTorrent/TorrentTest.php index 9e22153..763484a 100644 --- a/tests/PHP/BitTorrent/TorrentTest.php +++ b/tests/PHP/BitTorrent/TorrentTest.php @@ -420,20 +420,6 @@ public function testSaveWithInvalidExtra() { unlink($target); } - /** - * Try to save when no announce has been given. The code we are testing is AFTER the code that - * checks if the file specified is writeable, so make sure the argument to save() is a file that - * is writeable. - * - * @expectedException RuntimeException - * @expectedExceptionMessage Announce URL is missing - * @covers PHP\BitTorrent\Torrent::save - */ - public function testSaveWithNoAnnounce() { - $target = tempnam(sys_get_temp_dir(), 'PHP\BitTorrent'); - $this->torrent->save($target); - } - /** * @expectedException RuntimeException * @expectedExceptionMessage The info part of the torrent is not set. From eeab899be214f632168eb47f0d41e15fea452041 Mon Sep 17 00:00:00 2001 From: Vedmant Date: Tue, 11 Jul 2017 12:18:10 +0300 Subject: [PATCH 10/70] Added test for trackerless torrents, fixed issue with createFromPath method --- PHP/BitTorrent/Torrent.php | 2 +- tests/PHP/BitTorrent/TorrentTest.php | 43 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/PHP/BitTorrent/Torrent.php b/PHP/BitTorrent/Torrent.php index 698be81..6dc0645 100644 --- a/PHP/BitTorrent/Torrent.php +++ b/PHP/BitTorrent/Torrent.php @@ -164,7 +164,7 @@ static public function createFromTorrentFile($path, DecoderInterface $decoder = * @param string $announceUrl URL to the announce * @return Torrent Returns a new instance of this class */ - static public function createFromPath($path, $announceUrl) { + static public function createFromPath($path, $announceUrl = null) { // Create a new torrent instance $torrent = new static($announceUrl); diff --git a/tests/PHP/BitTorrent/TorrentTest.php b/tests/PHP/BitTorrent/TorrentTest.php index 763484a..ef96304 100644 --- a/tests/PHP/BitTorrent/TorrentTest.php +++ b/tests/PHP/BitTorrent/TorrentTest.php @@ -354,6 +354,49 @@ public function testSaveTorrent() { unlink($target); } + /** + * @covers PHP\BitTorrent\Torrent::createFromPath + * @covers PHP\BitTorrent\Torrent::setComment + * @covers PHP\BitTorrent\Torrent::setCreatedBy + * @covers PHP\BitTorrent\Torrent::setAnnounceList + * @covers PHP\BitTorrent\Torrent::save + * @covers PHP\BitTorrent\Torrent::createFromTorrentFile + * @covers PHP\BitTorrent\Torrent::getComment + * @covers PHP\BitTorrent\Torrent::getCreatedBy + * @covers PHP\BitTorrent\Torrent::getName + * @covers PHP\BitTorrent\Torrent::getSize + * @covers PHP\BitTorrent\Torrent::add + * @covers PHP\BitTorrent\Torrent::getFileList + * @covers PHP\BitTorrent\Torrent::getInfoPart + */ + public function testSaveTrackerlessTorrent() { + $path = __DIR__ . '/_files'; + $comment = 'Some comment'; + $createdBy = 'PHPUnit'; + $target = tempnam(sys_get_temp_dir(), 'PHP\BitTorrent'); + + if (!$target) { + $this->fail('Could not create file: ' . $target); + } + + $torrent = Torrent::createFromPath($path); + $torrent->setComment($comment) + ->setCreatedBy($createdBy) + ->save($target); + + // Now load the file and make sure the values are correct + $torrent = Torrent::createFromTorrentFile($target); + + $this->assertSame($comment, $torrent->getComment()); + $this->assertSame($createdBy, $torrent->getCreatedBy()); + $this->assertSame('_files', $torrent->getName()); + $this->assertEquals(902910, $torrent->getSize()); + $this->assertSame(7, count($torrent->getFileList())); + + // Remove the saved file + unlink($target); + } + /** * @covers PHP\BitTorrent\Torrent::createFromPath * @covers PHP\BitTorrent\Torrent::setExtraMeta From b17faec98eff3d1cb3ffe96b29d70ca88798a19b Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 12:16:48 +0100 Subject: [PATCH 11/70] Bump dependencies and update with regards to namespace. Also added some composer scripts as these will replace the tasks in the removed Rakefile --- Rakefile | 361 ---------------- composer.json | 28 +- composer.lock | 1121 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 1033 insertions(+), 477 deletions(-) delete mode 100644 Rakefile diff --git a/Rakefile b/Rakefile deleted file mode 100644 index 4edab71..0000000 --- a/Rakefile +++ /dev/null @@ -1,361 +0,0 @@ -require 'date' -require 'digest/md5' -require 'fileutils' -require 'nokogiri' - -basedir = "." -build = "#{basedir}/build" -source = "#{basedir}/PHP" - -desc "Task used by Jenkins-CI" -task :jenkins => [:lint, :prepare, :installdep, :phpunit, :phpdoc, :phploc, :phpcs_ci, :phpcb, :phpcpd, :phpmd, :phpmd_html] - -desc "Task used by Travis-CI" -task :travis => [:installdep, :phpunit] - -desc "Default task" -task :default => [:lint, :prepare, :installdep, :phpunit, :phpdoc, :phpcs] - -desc "Clean up and create artifact directories" -task :prepare do - puts "Prepare build" - - FileUtils.rm_rf build - FileUtils.mkdir build - - ["coverage", "logs", "docs", "code-browser"].each do |d| - FileUtils.mkdir "#{build}/#{d}" - end -end - -desc "Check syntax on all php files in the project" -task :lint do - puts "lint PHP files" - - `git ls-files "*.php"`.split("\n").each do |f| - begin - sh %{php -l #{f}} - rescue Exception - exit 1 - end - end -end - -desc "Install dependencies" -task :installdep do - if ENV["TRAVIS"] == "true" - system "composer --no-ansi install --dev" - else - Rake::Task["install_composer"].invoke - system "php -d \"apc.enable_cli=0\" composer.phar install --dev" - end -end - -desc "Update dependencies" -task :updatedep do - Rake::Task["install_composer"].invoke - system "php -d \"apc.enable_cli=0\" composer.phar update --dev" -end - -desc "Install/update composer itself" -task :install_composer do - if File.exists?("composer.phar") - system "php -d \"apc.enable_cli=0\" composer.phar self-update" - else - system "curl -s http://getcomposer.org/installer | php -d \"apc.enable_cli=0\"" - end -end - -desc "Run unit tests" -task :phpunit do - config = "phpunit.xml.dist" - - if ENV["TRAVIS"] == "true" - config = "phpunit.xml.travis" - elsif File.exists?("phpunit.xml") - config = "phpunit.xml" - end - - begin - sh %{vendor/bin/phpunit --verbose -c #{config}} - rescue Exception - exit 1 - end -end - -desc "Generate API documentation using phpdoc" -task :phpdoc do - puts "Generate API docs" - system "phpdoc -d #{source} -t #{build}/docs --title \"PHP BitTorrent API Documentation\"" -end - -desc "Generate phploc logs" -task :phploc do - puts "Generate LOC data" - system "phploc --log-csv #{build}/logs/phploc.csv --log-xml #{build}/logs/phploc.xml #{source}" -end - -desc "Generate checkstyle.xml using PHP_CodeSniffer" -task :phpcs_ci do - puts "Generate CS violation reports" - system "phpcs --report=checkstyle --report-file=#{build}/logs/checkstyle.xml --standard=Imbo #{source}" -end - -desc "Check CS" -task :phpcs do - puts "Check CS" - system "phpcs --standard=Imbo #{source}" -end - -desc "Aggregate tool output with PHP_CodeBrowser" -task :phpcb do - puts "Generate codebrowser" - system "phpcb --source #{source} --output #{build}/code-browser" -end - -desc "Generate pmd-cpd.xml using PHPCPD" -task :phpcpd do - puts "Generate CPD logs" - system "phpcpd --log-pmd #{build}/logs/pmd-cpd.xml #{source}" -end - -desc "Generate pmd.xml using PHPMD (configuration in phpmd.xml)" -task :phpmd do - puts "Generate mess detection logs" - system "phpmd #{source} xml #{basedir}/phpmd.xml --reportfile #{build}/logs/pmd.xml" -end - -desc "Generate pmd.html using PHPMD (configuration in phpmd.xml)" -task :phpmd_html do - puts "Generate mess detection HTML" - system "phpmd #{source} html #{basedir}/phpmd.xml --reportfile #{build}/logs/pmd.html" -end - -desc "Create a PEAR package" -task :generate_pear_package, :version do |t, args| - puts "Create a PEAR package" - - version = args[:version] - - if /^[\d]+\.[\d]+\.[\d]+$/ =~ version - now = DateTime.now - hash = Digest::MD5.new - xml = Nokogiri::XML::Builder.new { |xml| - xml.package(:version => "2.0", :xmlns => "http://pear.php.net/dtd/package-2.0", "xmlns:tasks" => "http://pear.php.net/dtd/tasks-1.0", "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", "xsi:schemaLocation" => ["http://pear.php.net/dtd/tasks-1.0", "http://pear.php.net/dtd/tasks-1.0.xsd", "http://pear.php.net/dtd/package-2.0", "http://pear.php.net/dtd/package-2.0.xsd"].join(" ")) { - xml.name "PHP_BitTorrent" - xml.channel "pear.starzinger.net" - xml.summary "Components for working with torrent files and the BitTorrent format in PHP" - xml.description "PHP_BitTorrent is a set of components that can be used to interact with torrent files (read+write) and encode/decode to/from the BitTorrent format" - xml.lead { - xml.name "Christer Edvartsen" - xml.user "christeredvartsen" - xml.email "cogo@starzinger.net" - xml.active "yes" - } - xml.date now.strftime('%Y-%m-%d') - xml.time now.strftime('%H:%M:%S') - xml.version { - xml.release version - xml.api version - } - xml.stability { - xml.release "stable" - xml.api "stable" - } - xml.license "MIT", :uri => "http://www.opensource.org/licenses/mit-license.php" - xml.notes "http://github.com/christeredvartsen/php-bittorrent/blob/#{version}/README.markdown" - xml.contents { - xml.dir(:name => "/") { - # PHP files - `git ls-files PHP`.split("\n").each { |f| - xml.file(:md5sum => hash.hexdigest(File.read(f)), :role => "php", :name => f) - } - - # Misc - ["README.markdown", "LICENSE", "ChangeLog.markdown"].each { |f| - xml.file(:md5sum => hash.hexdigest(File.read(f)), :role => "doc", :name => f) - } - } - } - xml.dependencies { - xml.required { - xml.php { - xml.min "5.3.2" - } - xml.pearinstaller { - xml.min "1.9.0" - } - } - } - xml.phprelease - } - } - - # Write XML to package.xml - File.open("package.xml", "w") { |f| - f.write(xml.to_xml) - } - - # Generate pear package - system "pear package" - - File.unlink("package.xml") - else - puts "'#{version}' is not a valid version" - exit 1 - end -end - -desc "Generate phar archive" -task :generate_phar_archive, :version do |t, args| - puts "Generate PHAR archive" - - version = args[:version] - - if /^[\d]+\.[\d]+\.[\d]+$/ =~ version - # Path to stub - stub = "#{basedir}/stub.php" - - # Generate stub - File.open(stub, "w") do |f| - f.write(<<-STUB) - - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * @package PHP\BitTorrent - * @author Christer Edvartsen - * @copyright Copyright (c) 2011-2013, Christer Edvartsen - * @license http://www.opensource.org/licenses/mit-license MIT License - * @link https://github.com/christeredvartsen/php-bittorrent - * @version #{version} - */ - -Phar::mapPhar(); - -$basePath = 'phar://' . __FILE__; - -spl_autoload_register(function($class) use ($basePath) { - if (strpos($class, 'PHP\\\\BitTorrent\\\\') !== 0) { - return false; - } - - $file = $basePath . DIRECTORY_SEPARATOR . substr(str_replace('\\\\', DIRECTORY_SEPARATOR, $class), 4) . '.php'; - - if (file_exists($file)) { - require $file; - return true; - } - - return false; -}); - -__HALT_COMPILER(); -STUB - end - - # Generate the phar archive - system "phar-build -s #{source} -S #{stub} --phar #{basedir}/php-bittorrent.phar --ns --strip-files '.php$'" - - # Remove the stub - File.unlink("stub.php") - else - puts "'#{version}' is not a valid version" - exit 1 - end -end - -desc "Publish a PEAR package to pear.starzinger.net" -task :publish_pear_package, :version do |t, args| - puts "Publish PEAR package" - version = args[:version] - - if /^[\d]+\.[\d]+\.[\d]+$/ =~ version - # Generate PEAR package - Rake::Task["generate_pear_package"].invoke(version) - - package = "PHP_BitTorrent-#{version}.tgz" - - if File.exists?(package) - wd = Dir.getwd - Dir.chdir("/home/christer/dev/christeredvartsen.github.com") - system "git pull origin master" - system "pirum add . #{wd}/#{package}" - system "git add --all" - system "git commit -am 'Added #{package[0..-5]}'" - system "git push" - Dir.chdir(wd) - File.unlink(package) - else - puts "#{package} does not exist. Run the pear task first to create the package" - end - else - puts "'#{version}' is not a valid version" - exit 1 - end -end - -desc "Tag current state of the master branch and push it to GitHub" -task :tag_master_branch, :version do |t, args| - puts "Tag release" - version = args[:version] - - if /^[\d]+\.[\d]+\.[\d]+$/ =~ version - # Checkout the master branch - system "git checkout master" - - # Merge in the current state of the develop branch - system "git merge develop" - - # Update phar arhive - Rake::Task["generate_phar_archive"].invoke(version) - system "git add php-bittorrent.phar" - system "git commit -m 'Updated phar archive' php-bittorrent.phar" - - # Tag release and push - system "git tag #{version}" - system "git push" - system "git push --tags" - system "git checkout develop" - else - puts "'#{version}' is not a valid version" - exit 1 - end -end - -desc "Release a new version" -task :release, :version do |t, args| - puts "Release a new version of the library" - version = args[:version] - - if /^[\d]+\.[\d]+\.[\d]+$/ =~ version - # Publish to the PEAR channel - Rake::Task["publish_pear_package"].invoke(version) - - # Tag the current state of master and push to GitHub - Rake::Task["tag_master_branch"].invoke(version) - else - puts "'#{version}' is not a valid version" - exit 1 - end -end diff --git a/composer.json b/composer.json index d936ba3..8cfc840 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "christeredvartsen/php-bittorrent", "type": "library", - "description": "PHP\\BitTorrent is a set of components that can be used to interact with torrent files (read+write) and classes that can encode/decode to/from the BitTorrent format.", + "description": "PHP BitTorrent is a set of components that can be used to interact with torrent files (read+write) and classes that can encode/decode to/from the BitTorrent format.", "keywords": ["bittorrent", "torrent"], "homepage": "https://github.com/christeredvartsen/php-bittorrent", "license": "MIT", @@ -12,15 +12,35 @@ } ], "require": { - "php": ">=5.3.2" + "php": ">=5.6.0" }, "require-dev": { - "phpunit/phpunit": "~3.7" + "phpunit/phpunit": "^5.7" }, "support": { + "source": "https://github.com/christeredvartsen/php-bittorrent", "issues": "https://github.com/christeredvartsen/php-bittorrent/issues" }, "autoload": { - "psr-0": { "PHP\\BitTorrent": "" } + "psr-4": { + "BitTorrent\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "BitTorrent\\": "tests/" + } + }, + "scripts": { + "lint": "for file in `git ls-files '*php'`; do php -l $file; done", + "prepare": [ + "rm -rf build", + "mkdir build", + "mkdir build/coverage" + ], + "test-phpunit": "vendor/bin/phpunit --verbose", + "test": [ + "@test-phpunit" + ] } } diff --git a/composer.lock b/composer.lock index 36c002a..8ba09ab 100644 --- a/composer.lock +++ b/composer.lock @@ -1,54 +1,362 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "d4c5831d3da5ed2f09faabe1130bd05e", + "hash": "2f47f1c31a1053b0bcbc924d5f3657ae", + "content-hash": "6bb05ab3786a98c7cf5ce2d4b7616823", "packages": [], "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "shasum": "" + }, + "require": { + "php": ">=5.3,<8.0-DEV" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2015-06-14 21:17:01" + }, + { + "name": "myclabs/deep-copy", + "version": "1.5.5", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/399c1f9781e222f6eb6cc238796f5200d1b7f108", + "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "doctrine/collections": "1.*", + "phpunit/phpunit": "~4.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "homepage": "https://github.com/myclabs/DeepCopy", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2016-10-31 17:19:45" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "time": "2015-12-27 11:43:31" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0@dev", + "phpdocumentor/type-resolver": "^0.2.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2016-09-30 07:12:33" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.2.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", + "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", + "shasum": "" + }, + "require": { + "php": ">=5.5", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "time": "2016-11-25 06:54:22" + }, + { + "name": "phpspec/prophecy", + "version": "v1.6.2", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", + "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", + "sebastian/comparator": "^1.1", + "sebastian/recursion-context": "^1.0|^2.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.0", + "phpunit/phpunit": "^4.8 || ^5.6.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2016-11-21 14:58:47" + }, { "name": "phpunit/php-code-coverage", - "version": "1.2.18", + "version": "4.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b" + "reference": "903fd6318d0a90b4770a009ff73e4a4e9c437929" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", - "reference": "fe2466802556d3fe4e4d1d58ffd3ccfd0a19be0b", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/903fd6318d0a90b4770a009ff73e4a4e9c437929", + "reference": "903fd6318d0a90b4770a009ff73e4a4e9c437929", "shasum": "" }, "require": { - "php": ">=5.3.3", - "phpunit/php-file-iterator": ">=1.3.0@stable", - "phpunit/php-text-template": ">=1.2.0@stable", - "phpunit/php-token-stream": ">=1.1.3,<1.3.0" + "php": "^5.6 || ^7.0", + "phpunit/php-file-iterator": "~1.3", + "phpunit/php-text-template": "~1.2", + "phpunit/php-token-stream": "^1.4.2", + "sebastian/code-unit-reverse-lookup": "~1.0", + "sebastian/environment": "^1.3.2 || ^2.0", + "sebastian/version": "~1.0|~2.0" }, "require-dev": { - "phpunit/phpunit": "3.7.*@dev" + "ext-xdebug": ">=2.1.4", + "phpunit/phpunit": "^5.4" }, "suggest": { "ext-dom": "*", - "ext-xdebug": ">=2.0.5" + "ext-xdebug": ">=2.4.0", + "ext-xmlwriter": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "4.0.x-dev" } }, "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -66,35 +374,37 @@ "testing", "xunit" ], - "time": "2014-09-02 10:13:14" + "time": "2016-11-28 16:00:31" }, { "name": "phpunit/php-file-iterator", - "version": "1.3.4", + "version": "1.4.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb" + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb", - "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", "shasum": "" }, "require": { "php": ">=5.3.3" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4.x-dev" + } + }, "autoload": { "classmap": [ - "File/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -111,20 +421,20 @@ "filesystem", "iterator" ], - "time": "2013-10-10 15:34:57" + "time": "2016-10-03 07:40:28" }, { "name": "phpunit/php-text-template", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { @@ -133,20 +443,17 @@ "type": "library", "autoload": { "classmap": [ - "Text/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -155,35 +462,35 @@ "keywords": [ "template" ], - "time": "2014-01-30 17:20:04" + "time": "2015-06-21 13:50:34" }, { "name": "phpunit/php-timer", - "version": "1.0.5", + "version": "1.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", "shasum": "" }, "require": { "php": ">=5.3.3" }, + "require-dev": { + "phpunit/phpunit": "~4|~5" + }, "type": "library", "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -199,49 +506,48 @@ "keywords": [ "timer" ], - "time": "2013-08-02 07:42:54" + "time": "2016-05-12 18:03:57" }, { "name": "phpunit/php-token-stream", - "version": "1.2.2", + "version": "1.4.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32" + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32", - "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", + "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", "shasum": "" }, "require": { "ext-tokenizer": "*", "php": ">=5.3.3" }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2-dev" + "dev-master": "1.4-dev" } }, "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "email": "sebastian@phpunit.de" } ], "description": "Wrapper around PHP's tokenizer extension.", @@ -249,62 +555,71 @@ "keywords": [ "tokenizer" ], - "time": "2014-03-03 05:10:30" + "time": "2016-11-15 14:06:22" }, { "name": "phpunit/phpunit", - "version": "3.7.38", + "version": "5.7.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6" + "reference": "af91da3f2671006ff5d0628023de3b7ac4d1ef09" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/38709dc22d519a3d1be46849868aa2ddf822bcf6", - "reference": "38709dc22d519a3d1be46849868aa2ddf822bcf6", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/af91da3f2671006ff5d0628023de3b7ac4d1ef09", + "reference": "af91da3f2671006ff5d0628023de3b7ac4d1ef09", "shasum": "" }, "require": { - "ext-ctype": "*", "ext-dom": "*", "ext-json": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-spl": "*", - "php": ">=5.3.3", - "phpunit/php-code-coverage": "~1.2", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.1", - "phpunit/php-timer": "~1.0", - "phpunit/phpunit-mock-objects": "~1.2", - "symfony/yaml": "~2.0" + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "myclabs/deep-copy": "~1.3", + "php": "^5.6 || ^7.0", + "phpspec/prophecy": "^1.6.2", + "phpunit/php-code-coverage": "^4.0.3", + "phpunit/php-file-iterator": "~1.4", + "phpunit/php-text-template": "~1.2", + "phpunit/php-timer": "^1.0.6", + "phpunit/phpunit-mock-objects": "^3.2", + "sebastian/comparator": "~1.2.2", + "sebastian/diff": "~1.2", + "sebastian/environment": "^1.3.4 || ^2.0", + "sebastian/exporter": "~2.0", + "sebastian/global-state": "^1.0 || ^2.0", + "sebastian/object-enumerator": "~2.0", + "sebastian/resource-operations": "~1.0", + "sebastian/version": "~1.0|~2.0", + "symfony/yaml": "~2.1|~3.0" + }, + "conflict": { + "phpdocumentor/reflection-docblock": "3.0.2" }, "require-dev": { - "pear-pear.php.net/pear": "1.9.4" + "ext-pdo": "*" }, "suggest": { + "ext-xdebug": "*", "phpunit/php-invoker": "~1.1" }, "bin": [ - "composer/bin/phpunit" + "phpunit" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "3.7.x-dev" + "dev-master": "5.7.x-dev" } }, "autoload": { "classmap": [ - "PHPUnit/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "", - "../../symfony/yaml/" - ], "license": [ "BSD-3-Clause" ], @@ -316,45 +631,55 @@ } ], "description": "The PHP Unit Testing framework.", - "homepage": "http://www.phpunit.de/", + "homepage": "https://phpunit.de/", "keywords": [ "phpunit", "testing", "xunit" ], - "time": "2014-10-17 09:04:17" + "time": "2016-12-13 16:19:44" }, { "name": "phpunit/phpunit-mock-objects", - "version": "1.2.3", + "version": "3.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875" + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/5794e3c5c5ba0fb037b11d8151add2a07fa82875", - "reference": "5794e3c5c5ba0fb037b11d8151add2a07fa82875", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", + "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", "shasum": "" }, "require": { - "php": ">=5.3.3", - "phpunit/php-text-template": ">=1.1.1@stable" + "doctrine/instantiator": "^1.0.2", + "php": "^5.6 || ^7.0", + "phpunit/php-text-template": "^1.2", + "sebastian/exporter": "^1.2 || ^2.0" + }, + "conflict": { + "phpunit/phpunit": "<5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.4" }, "suggest": { "ext-soap": "*" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev" + } + }, "autoload": { "classmap": [ - "PHPUnit/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], @@ -371,62 +696,634 @@ "mock", "xunit" ], - "time": "2013-01-13 10:24:48" + "time": "2016-12-08 20:27:08" }, { - "name": "symfony/yaml", - "version": "v2.5.6", - "target-dir": "Symfony/Component/Yaml", + "name": "sebastian/code-unit-reverse-lookup", + "version": "1.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/Yaml.git", - "reference": "2d9f527449cabfa8543dd7fa3a466d6ae83d6726" + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/2d9f527449cabfa8543dd7fa3a466d6ae83d6726", - "reference": "2d9f527449cabfa8543dd7fa3a466d6ae83d6726", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "~5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.5-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-0": { - "Symfony\\Component\\Yaml\\": "" + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "time": "2016-02-13 06:45:14" + }, + { + "name": "sebastian/comparator", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f", + "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/diff": "~1.2", + "sebastian/exporter": "~1.2 || ~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" }, { - "name": "Fabien Potencier", + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "http://www.github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2016-11-19 09:18:40" + }, + { + "name": "sebastian/diff", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", + "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff" + ], + "time": "2015-12-08 07:14:41" + }, + { + "name": "sebastian/environment", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "time": "2016-11-26 07:53:53" + }, + { + "name": "sebastian/exporter", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "sebastian/recursion-context": "~2.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2016-11-19 08:54:04" + }, + { + "name": "sebastian/global-state", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.2" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "time": "2015-10-12 03:26:01" + }, + { + "name": "sebastian/object-enumerator", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", + "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "sebastian/recursion-context": "~2.0" + }, + "require-dev": { + "phpunit/phpunit": "~5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "time": "2016-11-19 07:35:10" + }, + { + "name": "sebastian/recursion-context", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2016-11-19 07:33:16" + }, + { + "name": "sebastian/resource-operations", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "shasum": "" + }, + "require": { + "php": ">=5.6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "time": "2015-07-28 20:34:47" + }, + { + "name": "sebastian/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", + "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "time": "2016-10-03 07:35:21" + }, + { + "name": "symfony/yaml", + "version": "v3.2.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "a7095af4b97a0955f85c8989106c249fa649011f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/a7095af4b97a0955f85c8989106c249fa649011f", + "reference": "a7095af4b97a0955f85c8989106c249fa649011f", + "shasum": "" + }, + "require": { + "php": ">=5.5.9" + }, + "require-dev": { + "symfony/console": "~2.8|~3.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Yaml Component", - "homepage": "http://symfony.com", - "time": "2014-10-01 05:50:18" + "homepage": "https://symfony.com", + "time": "2016-12-10 10:07:06" + }, + { + "name": "webmozart/assert", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", + "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2016-11-23 20:04:58" } ], "aliases": [], "minimum-stability": "stable", "stability-flags": [], "prefer-stable": false, + "prefer-lowest": false, "platform": { - "php": ">=5.3.2" + "php": ">=5.6.0" }, "platform-dev": [] } From 6ac7f91af344dbc1917cbc4114f208f6a4ff5bde Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 12:17:22 +0100 Subject: [PATCH 12/70] Remove logging from the dist PHPUnit configuration file --- phpunit.xml.dist | 11 +++-------- phpunit.xml.travis | 8 -------- 2 files changed, 3 insertions(+), 16 deletions(-) delete mode 100644 phpunit.xml.travis diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 38f89c6..c8a62cd 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,18 +1,13 @@ - + - tests/PHP + tests - - - - - - PHP + src diff --git a/phpunit.xml.travis b/phpunit.xml.travis deleted file mode 100644 index 83d92b8..0000000 --- a/phpunit.xml.travis +++ /dev/null @@ -1,8 +0,0 @@ - - - - - tests/PHP - - - From fa2a009441dc8eb3cf946aee372913afd47e254a Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 12:17:52 +0100 Subject: [PATCH 13/70] Test on php 5.6 and 7.0, and use the composer scripts for executing tests --- .travis.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index d058082..66f2f93 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,13 @@ language: php + php: - - 5.3 - - 5.4 + - 5.6 + - 7.0 + before_script: - - "gem install nokogiri" -script: rake travis + - composer self-update + - composer install --prefer-source + +script: + - composer lint + - composer test From 5eb39b6688b6e3790017ef5e9fad17ab2a4abc57 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 12:18:05 +0100 Subject: [PATCH 14/70] Moved to correct dir --- {PHP/BitTorrent => src}/Decoder.php | 0 {PHP/BitTorrent => src}/DecoderInterface.php | 0 {PHP/BitTorrent => src}/Encoder.php | 0 {PHP/BitTorrent => src}/EncoderInterface.php | 0 {PHP/BitTorrent => src}/Torrent.php | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename {PHP/BitTorrent => src}/Decoder.php (100%) rename {PHP/BitTorrent => src}/DecoderInterface.php (100%) rename {PHP/BitTorrent => src}/Encoder.php (100%) rename {PHP/BitTorrent => src}/EncoderInterface.php (100%) rename {PHP/BitTorrent => src}/Torrent.php (100%) diff --git a/PHP/BitTorrent/Decoder.php b/src/Decoder.php similarity index 100% rename from PHP/BitTorrent/Decoder.php rename to src/Decoder.php diff --git a/PHP/BitTorrent/DecoderInterface.php b/src/DecoderInterface.php similarity index 100% rename from PHP/BitTorrent/DecoderInterface.php rename to src/DecoderInterface.php diff --git a/PHP/BitTorrent/Encoder.php b/src/Encoder.php similarity index 100% rename from PHP/BitTorrent/Encoder.php rename to src/Encoder.php diff --git a/PHP/BitTorrent/EncoderInterface.php b/src/EncoderInterface.php similarity index 100% rename from PHP/BitTorrent/EncoderInterface.php rename to src/EncoderInterface.php diff --git a/PHP/BitTorrent/Torrent.php b/src/Torrent.php similarity index 100% rename from PHP/BitTorrent/Torrent.php rename to src/Torrent.php From 333b7563dcb77e5fc24df07efccc673b7a1ef728 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 12:18:23 +0100 Subject: [PATCH 15/70] Update README with new namespaces and other details regarding next major version --- README.markdown | 96 +++++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/README.markdown b/README.markdown index 988ace1..2482b1e 100644 --- a/README.markdown +++ b/README.markdown @@ -1,60 +1,50 @@ -# PHP\_BitTorrent -**PHP\_BitTorrent** is a set of components that can be used to interact with torrent files (read+write) and encode/decode to/from the BitTorrent format. +# PHP BitTorrent +**PHP BitTorrent** is a set of components that can be used to interact with torrent files (read+write) and encode/decode to/from the BitTorrent format. [![Current Build Status](https://secure.travis-ci.org/christeredvartsen/php-bittorrent.png)](http://travis-ci.org/christeredvartsen/php-bittorrent) ## Requirements -PHP\_BitTorrent requires PHP 5.3.x or above. The recommended version is 5.3.2 or newer. +PHP BitTorrent requires PHP 5.6 or above. ## Installation -PHP\_BitTorrent can be installed using PEAR, Composer or PHAR. - -### PEAR -``` -sudo pear config-set auto_discover 1 -sudo pear install --alldeps pear.starzinger.net/PHP_BitTorrent -``` - -### Composer -Simply specify `christeredvartsen/php-bittorrent` in your dependencies. The different versions are listed at the [Packagist site](https://packagist.org/packages/christeredvartsen/php-bittorrent). - -### PHAR -You can also download [php-bittorrent.phar](https://github.com/christeredvartsen/php-bittorrent/raw/master/php-bittorrent.phar) and simply require that file where you want to use PHP_BitTorrent. - -```php -encodeString('Some string')); // string(14) "11:Some string" var_dump($encoder->encodeInteger(42)); // int(42) -var_dump($encoder->encodeList(array(1, 2, 3)); // string(11) "li1ei2ei3ee" -var_dump($encoder->encodeDictionary(array('foo' => 'bar', 'bar' => 'foo')); // string(22) "d3:foo3:bar3:bar3:fooe" +var_dump($encoder->encodeList([1, 2, 3]); // string(11) "li1ei2ei3ee" +var_dump($encoder->encodeDictionary(['foo' => 'bar', 'bar' => 'foo']); // string(22) "d3:foo3:bar3:bar3:fooe" ``` -There is also a convenience method simply called `encode` in the `PHP\BitTorrent\Encoder` class that can be used to encode all encodable variables (integers, strings and arrays). +There is also a convenience method simply called `encode` in the `BitTorrent\Encoder` class that can be used to encode all encodable variables (integers, strings and arrays). ### Decode BitTorrent encoded data ```php decodeString('11:Some string')); // string(11) "Some string" var_dump($decoder->decodeInteger('i42e')); // int(42) @@ -70,39 +60,51 @@ The decoder class also has a method for decoding a torrent file (which is an enc ```php decodeFile('/path/to/file.torrent'); ``` ### Create new torrent files and open existing ones -The `PHP\BitTorrent\Torrent` class represents a torrent file and can be used to create torrent files. +The `BitTorrent\Torrent` class represents a torrent file and can be used to create torrent files. ```php setComment('Some comment') - ->save('/save/to/path/file.torrent'); +$torrent + ->setComment('Some comment') + ->save('/save/to/path/file.torrent'); ``` The class can also load a torrent file: ```php setAnnounce('http://tracker/announce.php') // Override announce in original file - ->setComment('Some comment') // Override commend in original file - ->save('/save/to/path/file.torrent'); // Save to a new file +$torrent + ->setAnnounce('http://tracker/announce.php') // Override announce in original file + ->setComment('Some comment') // Override commend in original file + ->save('/save/to/path/file.torrent'); // Save to a new file ``` ### 32-bit platforms On 32-bit platforms these components work slightly different with regards to integers: -* The generic `PHP\BitTorrent\Encoder::encode` method will encode both integers and strings containing numerics as strings (strings containing floating point values are still treated as regular strings). -* The `PHP\BitTorrent\Decoder::decodeInteger` method will return values as strings, and not integers. -* The `PHP\BitTorrent\Torrent::getSize` method will use the [bcadd](http://no2.php.net/manual/en/function.bcadd.php) function to calculate the size of the files in the torrent. +* The generic `BitTorrent\Encoder::encode` method will encode both integers and strings containing numerics as strings (strings containing floating point values are still treated as regular strings). +* The `BitTorrent\Decoder::decodeInteger` method will return values as strings, and not integers. +* The `BitTorrent\Torrent::getSize` method will use the [bcadd](http://no2.php.net/manual/en/function.bcadd.php) function to calculate the size of the files in the torrent. From 60c8b3e8d940f9e09ccb45149cc17794c51e891a Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 12:29:08 +0100 Subject: [PATCH 16/70] Require the autoloader directly from PHPUnits configuration file --- tests/bootstrap.php | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 tests/bootstrap.php diff --git a/tests/bootstrap.php b/tests/bootstrap.php deleted file mode 100644 index bee858d..0000000 --- a/tests/bootstrap.php +++ /dev/null @@ -1,11 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE file that was - * distributed with this source code. - */ - -require_once __DIR__ . '/../vendor/autoload.php'; From 92ae6855e5489997abf95a7545a14531fda001d4 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 12:29:35 +0100 Subject: [PATCH 17/70] Move test files to correct dir --- tests/{PHP => }/BitTorrent/DecoderTest.php | 0 tests/{PHP => }/BitTorrent/EncoderTest.php | 0 tests/{PHP => }/BitTorrent/TorrentTest.php | 0 .../{PHP => }/BitTorrent/_extra_files/extra.torrent | 0 .../_files/file_with_private_set_to_0.torrent | 0 .../_files/file_with_private_set_to_1.torrent | 0 .../BitTorrent/_files/large_file.img.torrent | Bin .../{PHP => }/BitTorrent/_files/large_files.torrent | Bin .../BitTorrent/_files/testMissingAnnounce.torrent | 0 .../BitTorrent/_files/testMissingInfo.torrent | 0 tests/{PHP => }/BitTorrent/_files/valid.torrent | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename tests/{PHP => }/BitTorrent/DecoderTest.php (100%) rename tests/{PHP => }/BitTorrent/EncoderTest.php (100%) rename tests/{PHP => }/BitTorrent/TorrentTest.php (100%) rename tests/{PHP => }/BitTorrent/_extra_files/extra.torrent (100%) rename tests/{PHP => }/BitTorrent/_files/file_with_private_set_to_0.torrent (100%) rename tests/{PHP => }/BitTorrent/_files/file_with_private_set_to_1.torrent (100%) rename tests/{PHP => }/BitTorrent/_files/large_file.img.torrent (100%) rename tests/{PHP => }/BitTorrent/_files/large_files.torrent (100%) rename tests/{PHP => }/BitTorrent/_files/testMissingAnnounce.torrent (100%) rename tests/{PHP => }/BitTorrent/_files/testMissingInfo.torrent (100%) rename tests/{PHP => }/BitTorrent/_files/valid.torrent (100%) diff --git a/tests/PHP/BitTorrent/DecoderTest.php b/tests/BitTorrent/DecoderTest.php similarity index 100% rename from tests/PHP/BitTorrent/DecoderTest.php rename to tests/BitTorrent/DecoderTest.php diff --git a/tests/PHP/BitTorrent/EncoderTest.php b/tests/BitTorrent/EncoderTest.php similarity index 100% rename from tests/PHP/BitTorrent/EncoderTest.php rename to tests/BitTorrent/EncoderTest.php diff --git a/tests/PHP/BitTorrent/TorrentTest.php b/tests/BitTorrent/TorrentTest.php similarity index 100% rename from tests/PHP/BitTorrent/TorrentTest.php rename to tests/BitTorrent/TorrentTest.php diff --git a/tests/PHP/BitTorrent/_extra_files/extra.torrent b/tests/BitTorrent/_extra_files/extra.torrent similarity index 100% rename from tests/PHP/BitTorrent/_extra_files/extra.torrent rename to tests/BitTorrent/_extra_files/extra.torrent diff --git a/tests/PHP/BitTorrent/_files/file_with_private_set_to_0.torrent b/tests/BitTorrent/_files/file_with_private_set_to_0.torrent similarity index 100% rename from tests/PHP/BitTorrent/_files/file_with_private_set_to_0.torrent rename to tests/BitTorrent/_files/file_with_private_set_to_0.torrent diff --git a/tests/PHP/BitTorrent/_files/file_with_private_set_to_1.torrent b/tests/BitTorrent/_files/file_with_private_set_to_1.torrent similarity index 100% rename from tests/PHP/BitTorrent/_files/file_with_private_set_to_1.torrent rename to tests/BitTorrent/_files/file_with_private_set_to_1.torrent diff --git a/tests/PHP/BitTorrent/_files/large_file.img.torrent b/tests/BitTorrent/_files/large_file.img.torrent similarity index 100% rename from tests/PHP/BitTorrent/_files/large_file.img.torrent rename to tests/BitTorrent/_files/large_file.img.torrent diff --git a/tests/PHP/BitTorrent/_files/large_files.torrent b/tests/BitTorrent/_files/large_files.torrent similarity index 100% rename from tests/PHP/BitTorrent/_files/large_files.torrent rename to tests/BitTorrent/_files/large_files.torrent diff --git a/tests/PHP/BitTorrent/_files/testMissingAnnounce.torrent b/tests/BitTorrent/_files/testMissingAnnounce.torrent similarity index 100% rename from tests/PHP/BitTorrent/_files/testMissingAnnounce.torrent rename to tests/BitTorrent/_files/testMissingAnnounce.torrent diff --git a/tests/PHP/BitTorrent/_files/testMissingInfo.torrent b/tests/BitTorrent/_files/testMissingInfo.torrent similarity index 100% rename from tests/PHP/BitTorrent/_files/testMissingInfo.torrent rename to tests/BitTorrent/_files/testMissingInfo.torrent diff --git a/tests/PHP/BitTorrent/_files/valid.torrent b/tests/BitTorrent/_files/valid.torrent similarity index 100% rename from tests/PHP/BitTorrent/_files/valid.torrent rename to tests/BitTorrent/_files/valid.torrent From 57173f6a76c8e76e2828c20a14e1ea488fe380b5 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 12:29:51 +0100 Subject: [PATCH 18/70] Fix namespaces and array notation --- src/Decoder.php | 2 +- src/DecoderInterface.php | 4 +++- src/Encoder.php | 16 ++++------------ src/EncoderInterface.php | 18 ++++++++++-------- src/Torrent.php | 34 +++++++++++++++++----------------- 5 files changed, 35 insertions(+), 39 deletions(-) diff --git a/src/Decoder.php b/src/Decoder.php index 8dbabf6..02f08b6 100644 --- a/src/Decoder.php +++ b/src/Decoder.php @@ -8,7 +8,7 @@ * distributed with this source code. */ -namespace PHP\BitTorrent; +namespace BitTorrent; use InvalidArgumentException; diff --git a/src/DecoderInterface.php b/src/DecoderInterface.php index 4fd2f19..2a7baf8 100644 --- a/src/DecoderInterface.php +++ b/src/DecoderInterface.php @@ -8,7 +8,9 @@ * distributed with this source code. */ -namespace PHP\BitTorrent; +namespace BitTorrent; + +use InvalidArgumentException; /** * Interface for decoders diff --git a/src/Encoder.php b/src/Encoder.php index e000db7..2c9b309 100644 --- a/src/Encoder.php +++ b/src/Encoder.php @@ -8,7 +8,7 @@ * distributed with this source code. */ -namespace PHP\BitTorrent; +namespace BitTorrent; use InvalidArgumentException; @@ -34,7 +34,7 @@ class Encoder implements EncoderInterface { * * @param array $params Parameters for the encoder */ - public function __construct(array $params = array()) { + public function __construct(array $params = []) { $this->params = array_replace($this->params, $params); } @@ -99,11 +99,7 @@ public function encodeString($string) { /** * {@inheritdoc} */ - public function encodeList($list) { - if (!is_array($list)) { - throw new InvalidArgumentException('Expected array, got: ' . gettype($list) . '.'); - } - + public function encodeList(array $list) { $ret = 'l'; foreach ($list as $value) { @@ -116,11 +112,7 @@ public function encodeList($list) { /** * {@inheritdoc} */ - public function encodeDictionary($dictionary) { - if (!is_array($dictionary)) { - throw new InvalidArgumentException('Expected array, got: ' . gettype($dictionary) . '.'); - } - + public function encodeDictionary(array $dictionary) { ksort($dictionary); $ret = 'd'; diff --git a/src/EncoderInterface.php b/src/EncoderInterface.php index 2c3ce3b..5846d2a 100644 --- a/src/EncoderInterface.php +++ b/src/EncoderInterface.php @@ -8,7 +8,9 @@ * distributed with this source code. */ -namespace PHP\BitTorrent; +namespace BitTorrent; + +use InvalidArgumentException; /** * Interface for encoders @@ -31,7 +33,7 @@ function setParam($key, $value); * * @param int|string|array $var The variable to encode * @return string Returns the encoded string - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ function encode($var); @@ -40,7 +42,7 @@ function encode($var); * * @param int|string $integer The integer to encode. Strings are supported on 32-bit platforms * @return string Returns the encoded string - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ function encodeInteger($integer); @@ -49,7 +51,7 @@ function encodeInteger($integer); * * @param string $string The string to encode * @return string Returns the encoded string - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ function encodeString($string); @@ -58,16 +60,16 @@ function encodeString($string); * * @param array $list The array to encode * @return string Returns the encoded string - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ - function encodeList($list); + function encodeList(array $list); /** * Encode a dictionary (associative PHP array) * * @param array $dictionary The array to encode * @return string Returns the encoded string - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ - function encodeDictionary($dictionary); + function encodeDictionary(array $dictionary); } diff --git a/src/Torrent.php b/src/Torrent.php index 6dc0645..82fb6cd 100644 --- a/src/Torrent.php +++ b/src/Torrent.php @@ -8,12 +8,12 @@ * distributed with this source code. */ -namespace PHP\BitTorrent; +namespace BitTorrent; -use RecursiveDirectoryIterator, - RecursiveIteratorIterator, - RuntimeException, - InvalidArgumentException; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use RuntimeException; +use InvalidArgumentException; /** * A class that represents a single torrent file @@ -169,7 +169,7 @@ static public function createFromPath($path, $announceUrl = null) { $torrent = new static($announceUrl); // Initialize array of the files to include in the torrent - $files = array(); + $files = []; // Generate an absolute path $absolutePath = realpath($path); @@ -178,10 +178,10 @@ static public function createFromPath($path, $announceUrl = null) { // See if we have a single file if (is_file($absolutePath)) { $pathIsFile = true; - $files[] = array( + $files[] = [ 'filename' => basename($absolutePath), 'filesize' => filesize($absolutePath), - ); + ]; } else if (is_dir($absolutePath)) { $dir = new RecursiveDirectoryIterator($absolutePath); $iterator = new RecursiveIteratorIterator($dir); @@ -193,22 +193,22 @@ static public function createFromPath($path, $announceUrl = null) { continue; } - $files[] = array( + $files[] = [ 'filename' => str_replace($absolutePath . DIRECTORY_SEPARATOR, '', (string) $entry), 'filesize' => $entry->getSize(), - ); + ]; } } else { throw new InvalidArgumentException('Invalid path: ' . $path); } // Initialize the info part of the torrent - $info = array( + $info = [ 'piece length' => pow(2, $torrent->getPieceLengthExp()) - ); + ]; // Initialize the pieces - $pieces = array(); + $pieces = []; // If we only have a single file, get the size of the file and set the name property if ($pathIsFile) { @@ -268,10 +268,10 @@ static public function createFromPath($path, $announceUrl = null) { $filename = $file['filename']; $filesize = $file['filesize']; - $info['files'][] = array( + $info['files'][] = [ 'length' => $filesize, 'path' => explode(DIRECTORY_SEPARATOR, $filename) - ); + ]; // Reset the position in the current file $position = 0; @@ -518,10 +518,10 @@ public function save($filename, EncoderInterface $encoder = null) { $createdAt = time(); } - $torrent = array( + $torrent = [ 'creation date' => $createdAt, 'info' => $info, - ); + ]; if (($announce = $this->getAnnounce()) !== null) { $torrent['announce'] = $announce; From 741802ebfb51493487d1671cea3095d22cb1ed27 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 12:31:59 +0100 Subject: [PATCH 19/70] Move files correctly this time --- tests/{BitTorrent => }/DecoderTest.php | 0 tests/{BitTorrent => }/EncoderTest.php | 0 tests/{BitTorrent => }/TorrentTest.php | 0 tests/{BitTorrent => }/_extra_files/extra.torrent | 0 .../_files/file_with_private_set_to_0.torrent | 0 .../_files/file_with_private_set_to_1.torrent | 0 .../{BitTorrent => }/_files/large_file.img.torrent | Bin tests/{BitTorrent => }/_files/large_files.torrent | Bin .../_files/testMissingAnnounce.torrent | 0 .../{BitTorrent => }/_files/testMissingInfo.torrent | 0 tests/{BitTorrent => }/_files/valid.torrent | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename tests/{BitTorrent => }/DecoderTest.php (100%) rename tests/{BitTorrent => }/EncoderTest.php (100%) rename tests/{BitTorrent => }/TorrentTest.php (100%) rename tests/{BitTorrent => }/_extra_files/extra.torrent (100%) rename tests/{BitTorrent => }/_files/file_with_private_set_to_0.torrent (100%) rename tests/{BitTorrent => }/_files/file_with_private_set_to_1.torrent (100%) rename tests/{BitTorrent => }/_files/large_file.img.torrent (100%) rename tests/{BitTorrent => }/_files/large_files.torrent (100%) rename tests/{BitTorrent => }/_files/testMissingAnnounce.torrent (100%) rename tests/{BitTorrent => }/_files/testMissingInfo.torrent (100%) rename tests/{BitTorrent => }/_files/valid.torrent (100%) diff --git a/tests/BitTorrent/DecoderTest.php b/tests/DecoderTest.php similarity index 100% rename from tests/BitTorrent/DecoderTest.php rename to tests/DecoderTest.php diff --git a/tests/BitTorrent/EncoderTest.php b/tests/EncoderTest.php similarity index 100% rename from tests/BitTorrent/EncoderTest.php rename to tests/EncoderTest.php diff --git a/tests/BitTorrent/TorrentTest.php b/tests/TorrentTest.php similarity index 100% rename from tests/BitTorrent/TorrentTest.php rename to tests/TorrentTest.php diff --git a/tests/BitTorrent/_extra_files/extra.torrent b/tests/_extra_files/extra.torrent similarity index 100% rename from tests/BitTorrent/_extra_files/extra.torrent rename to tests/_extra_files/extra.torrent diff --git a/tests/BitTorrent/_files/file_with_private_set_to_0.torrent b/tests/_files/file_with_private_set_to_0.torrent similarity index 100% rename from tests/BitTorrent/_files/file_with_private_set_to_0.torrent rename to tests/_files/file_with_private_set_to_0.torrent diff --git a/tests/BitTorrent/_files/file_with_private_set_to_1.torrent b/tests/_files/file_with_private_set_to_1.torrent similarity index 100% rename from tests/BitTorrent/_files/file_with_private_set_to_1.torrent rename to tests/_files/file_with_private_set_to_1.torrent diff --git a/tests/BitTorrent/_files/large_file.img.torrent b/tests/_files/large_file.img.torrent similarity index 100% rename from tests/BitTorrent/_files/large_file.img.torrent rename to tests/_files/large_file.img.torrent diff --git a/tests/BitTorrent/_files/large_files.torrent b/tests/_files/large_files.torrent similarity index 100% rename from tests/BitTorrent/_files/large_files.torrent rename to tests/_files/large_files.torrent diff --git a/tests/BitTorrent/_files/testMissingAnnounce.torrent b/tests/_files/testMissingAnnounce.torrent similarity index 100% rename from tests/BitTorrent/_files/testMissingAnnounce.torrent rename to tests/_files/testMissingAnnounce.torrent diff --git a/tests/BitTorrent/_files/testMissingInfo.torrent b/tests/_files/testMissingInfo.torrent similarity index 100% rename from tests/BitTorrent/_files/testMissingInfo.torrent rename to tests/_files/testMissingInfo.torrent diff --git a/tests/BitTorrent/_files/valid.torrent b/tests/_files/valid.torrent similarity index 100% rename from tests/BitTorrent/_files/valid.torrent rename to tests/_files/valid.torrent From cded3eecb36bcf2a393dccf0d7871fe42471dfad Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 12:32:19 +0100 Subject: [PATCH 20/70] Update ChangeLog with regards to new major version --- ChangeLog.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ChangeLog.markdown b/ChangeLog.markdown index 8f3165f..0d55aae 100644 --- a/ChangeLog.markdown +++ b/ChangeLog.markdown @@ -1,10 +1,12 @@ Changelog for PHP BitTorrent ===================== -Version 1.2.0 +Version 2.0.0 ------------- __N/A__ +* Bump PHP requirement from 5.3 to 5.6 +* Change namespace from PHP\BitTorrent to BitTorrent * Added method to check if the torrent is private (@stormwalkerec) Version 1.1.0 From 9b888d8808eca876cd53a8c94fca5ac59a201286 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 16:18:27 +0100 Subject: [PATCH 21/70] Ignore return statement only run on 32-bit systems in the code coverage report --- src/Decoder.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Decoder.php b/src/Decoder.php index 02f08b6..9ee7eb2 100644 --- a/src/Decoder.php +++ b/src/Decoder.php @@ -96,7 +96,10 @@ public function decodeInteger($integer) { return (int) $integer; } + // Return integer as a string on 32-bit systems + // @codeCoverageIgnoreStart return $integer; + // @codeCoverageIgnoreEnd } /** From aaf20db2bbcae22c2144263f774a80d255d1d39d Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 16:18:42 +0100 Subject: [PATCH 22/70] Update tests so they all pass --- tests/DecoderTest.php | 163 +++++++++++++------------ tests/EncoderTest.php | 149 ++++++++++------------- tests/TorrentTest.php | 273 ++++++++++++++++++------------------------ 3 files changed, 261 insertions(+), 324 deletions(-) diff --git a/tests/DecoderTest.php b/tests/DecoderTest.php index 9d0ad2a..7a8a6c7 100644 --- a/tests/DecoderTest.php +++ b/tests/DecoderTest.php @@ -1,21 +1,12 @@ - * - * For the full copyright and license information, please view the LICENSE file that was - * distributed with this source code. - */ +namespace BitTorrent; -namespace PHP\BitTorrent; +use PHPUnit_Framework_TestCase; /** - * @package UnitTests - * @author Christer Edvartsen - * @covers PHP\BitTorrent\Decoder + * @coversDefaultClass BitTorrent\Decoder */ -class DecoderTest extends \PHPUnit_Framework_TestCase { +class DecoderTest extends PHPUnit_Framework_TestCase { /** * @var Decoder */ @@ -23,18 +14,9 @@ class DecoderTest extends \PHPUnit_Framework_TestCase { /** * Set up the decoder - * - * @covers PHP\BitTorrent\Decoder::__construct */ public function setUp() { - $this->decoder = new Decoder(new Encoder()); - } - - /** - * Tear down the decoder - */ - public function tearDown() { - $this->decoder = null; + $this->decoder = new Decoder(); } /** @@ -43,16 +25,18 @@ public function tearDown() { * @return array[] */ public function getDecodeIntegerData() { - return array( - array('i1e', 1), - array('i-1e', -1), - array('i0e', 0), - ); + return [ + ['i1e', 1], + ['i-1e', -1], + ['i0e', 0], + ]; } /** - * @dataProvider getDecodeIntegerData() - * @covers PHP\BitTorrent\Decoder::decodeInteger + * @dataProvider getDecodeIntegerData + * @covers ::decodeInteger + * @param string $encoded + * @param int $value */ public function testDecoderInteger($encoded, $value) { $this->assertEquals($value, $this->decoder->decodeInteger($encoded)); @@ -64,33 +48,37 @@ public function testDecoderInteger($encoded, $value) { * @return array[] */ public function getDecodeInvalidIntegerData() { - return array( - array('i01e'), - array('i-01e'), - array('ifoobare'), - ); + return [ + ['i01e'], + ['i-01e'], + ['ifoobare'], + ]; } /** - * @dataProvider getDecodeInvalidIntegerData() + * @dataProvider getDecodeInvalidIntegerData + * @covers ::decodeInteger * @expectedException InvalidArgumentException - * @covers PHP\BitTorrent\Decoder::decodeInteger + * @expectedExceptionMessage Invalid integer value. + * @param string $value */ public function testDecodeInvalidInteger($value) { $this->decoder->decodeInteger($value); } /** + * @covers ::decodeInteger * @expectedException InvalidArgumentException - * @covers PHP\BitTorrent\Decoder::decodeInteger + * @expectedExceptionMessage Invalid integer. Integers must start wth "i" and end with "e". */ public function testDecodeStringAsInteger() { $this->decoder->decodeInteger('4:spam'); } /** + * @covers ::decodeInteger * @expectedException InvalidArgumentException - * @covers PHP\BitTorrent\Decoder::decodeInteger + * @expectedExceptionMessage Invalid integer. Integers must start wth "i" and end with "e". */ public function testDecodePartialInteger() { $this->decoder->decodeInteger('i10'); @@ -99,35 +87,39 @@ public function testDecodePartialInteger() { /** * Data provider * - * @return array + * @return array[] */ public function getDecodeStringData() { - return array( - array('4:spam', 'spam'), - array('11:test string', 'test string'), - array('3:foobar', 'foo'), - ); + return [ + ['4:spam', 'spam'], + ['11:test string', 'test string'], + ['3:foobar', 'foo'], + ]; } /** - * @dataProvider getDecodeStringData() - * @covers PHP\BitTorrent\Decoder::decodeString + * @dataProvider getDecodeStringData + * @covers ::decodeString + * @param string $encoded + * @param string $value */ public function testDecodeString($encoded, $value) { $this->assertSame($value, $this->decoder->decodeString($encoded)); } /** + * @covers ::decodeString * @expectedException InvalidArgumentException - * @covers PHP\BitTorrent\Decoder::decodeString + * @expectedExceptionMessage Invalid string. Strings consist of two parts separated by ":". */ public function testDecodeInvalidString() { $this->decoder->decodeString('4spam'); } /** + * @covers ::decodeString * @expectedException InvalidArgumentException - * @covers PHP\BitTorrent\Decoder::decodeString + * @expectedExceptionMessage The length of the string does not match the prefix of the encoded data. */ public function testDecodeStringWithInvalidLength() { $this->decoder->decodeString('6:spam'); @@ -139,22 +131,25 @@ public function testDecodeStringWithInvalidLength() { * @return array[] */ public function getDecodeListData() { - return array( - array('li1ei2ei3ee', array(1, 2, 3)), - ); + return [ + ['li1ei2ei3ee', [1, 2, 3]], + ]; } /** - * @dataProvider getDecodeListData() - * @covers PHP\BitTorrent\Decoder::decodeList + * @dataProvider getDecodeListData + * @covers ::decodeList + * @param string $encoded + * @param array $value */ - public function testDecodeList($encoded, $value) { + public function testDecodeList($encoded, array $value) { $this->assertEquals($value, $this->decoder->decodeList($encoded)); } /** + * @covers ::decodeList * @expectedException InvalidArgumentException - * @covers PHP\BitTorrent\Decoder::decodeList + * @expectedExceptionMessage Parameter is not an encoded list. */ public function testDecodeInvalidList() { $this->decoder->decodeList('4:spam'); @@ -166,22 +161,25 @@ public function testDecodeInvalidList() { * @return array[] */ public function getDecodeDictionaryData() { - return array( - array('d3:foo3:bar4:spam4:eggse', array('foo' => 'bar', 'spam' => 'eggs')), - ); + return [ + ['d3:foo3:bar4:spam4:eggse', ['foo' => 'bar', 'spam' => 'eggs']], + ]; } /** - * @dataProvider getDecodeDictionaryData() - * @covers PHP\BitTorrent\Decoder::decodeDictionary + * @dataProvider getDecodeDictionaryData + * @covers ::decodeDictionary + * @param string $encoded + * @param array $value */ - public function testDecodeDictionary($encoded, $value) { + public function testDecodeDictionary($encoded, array $value) { $this->assertSame($value, $this->decoder->decodeDictionary($encoded)); } /** + * @covers ::decodeDictionary * @expectedException InvalidArgumentException - * @covers PHP\BitTorrent\Decoder::decodeDictionary + * @expectedExceptionMessage Parameter is not an encoded dictionary. */ public function testDecodeInvalidDictionary() { $this->decoder->decodeDictionary('4:spam'); @@ -193,25 +191,29 @@ public function testDecodeInvalidDictionary() { * @return array[] */ public function getGenericDecodeData() { - return array( - array('i1e', 1), - array('4:spam', 'spam'), - array('li1ei2ei3ee', array(1, 2, 3)), - array('d3:foo3:bare', array('foo' => 'bar')), - ); + return [ + ['i1e', 1], + ['4:spam', 'spam'], + ['li1ei2ei3ee', [1, 2, 3]], + ['d3:foo3:bare', ['foo' => 'bar']], + ]; } /** - * @dataProvider getGenericDecodeData() - * @covers PHP\BitTorrent\Decoder::decode + * @dataProvider getGenericDecodeData + * @covers ::__construct + * @covers ::decode + * @param string $encoded + * @param int|string|array $value */ public function testGenericDecode($encoded, $value) { $this->assertEquals($value, $this->decoder->decode($encoded)); } /** + * @covers ::decode * @expectedException InvalidArgumentException - * @covers PHP\BitTorrent\Decoder::decode + * @expectedExceptionMessage Parameter is not correctly encoded. */ public function testGenericDecodeWithInvalidData() { $this->decoder->decode('foo'); @@ -220,35 +222,32 @@ public function testGenericDecodeWithInvalidData() { /** * @expectedException InvalidArgumentException * @expectedExceptionMessage Missing "announce" key - * @covers PHP\BitTorrent\Decoder::decodeFile + * @covers ::decodeFile */ public function testDecodeTorrentFileStrictWithMissingAnnounce() { - $file = __DIR__ . '/_files/testMissingAnnounce.torrent'; - $this->decoder->decodeFile($file, true); + $this->decoder->decodeFile(__DIR__ . '/_files/testMissingAnnounce.torrent', true); } /** * @expectedException InvalidArgumentException * @expectedExceptionMessage Missing "info" key - * @covers PHP\BitTorrent\Decoder::decodeFile + * @covers ::decodeFile */ public function testDecodeTorrentFileStrictWithMissingInfo() { - $file = __DIR__ . '/_files/testMissingInfo.torrent'; - $this->decoder->decodeFile($file, true); + $this->decoder->decodeFile(__DIR__ . '/_files/testMissingInfo.torrent', true); } /** * @expectedException InvalidArgumentException * @expectedExceptionMessage File - * @covers PHP\BitTorrent\Decoder::decodeFile + * @covers ::decodeFile */ public function testDecodeNonReadableFile() { - $file = __DIR__ . '/nonExistingFile'; - $this->decoder->decodeFile($file); + $this->decoder->decodeFile(__DIR__ . '/nonExistingFile'); } /** - * @covers PHP\BitTorrent\Decoder::decodeFile + * @covers ::decodeFile */ public function testDecodeFileWithStrictChecksEnabled() { $list = $this->decoder->decodeFile(__DIR__ . '/_files/valid.torrent', true); diff --git a/tests/EncoderTest.php b/tests/EncoderTest.php index 22567a2..d8836cf 100644 --- a/tests/EncoderTest.php +++ b/tests/EncoderTest.php @@ -1,21 +1,13 @@ - * - * For the full copyright and license information, please view the LICENSE file that was - * distributed with this source code. - */ +namespace BitTorrent; -namespace PHP\BitTorrent; +use PHPUnit_Framework_TestCase; +use stdClass; /** - * @package UnitTests - * @author Christer Edvartsen - * @covers PHP\BitTorrent\Encoder + * @coversDefaultClass BitTorrent\Encoder */ -class EncoderTest extends \PHPUnit_Framework_TestCase { +class EncoderTest extends PHPUnit_Framework_TestCase { /** * @var Encdoder */ @@ -28,30 +20,25 @@ public function setUp() { $this->encoder = new Encoder(); } - /** - * Tear down the encoder - */ - public function tearDown() { - $this->encoder = null; - } - /** * Data provider * * @return array[] */ public function getEncodeIntegerData() { - return array( - array(-1, 'i-1e'), - array(0, 'i0e'), - array(1, 'i1e'), - ); + return [ + [-1, 'i-1e'], + [0, 'i0e'], + [1, 'i1e'], + ]; } /** - * @dataProvider getEncodeIntegerData() - * @covers PHP\BitTorrent\Encoder::encodeInteger - * @covers PHP\BitTorrent\Encoder::isInt + * @dataProvider getEncodeIntegerData + * @covers ::encodeInteger + * @covers ::isInt + * @param int $value + * @param string $encoded */ public function testEncodeInteger($value, $encoded) { $this->assertSame($encoded, $this->encoder->encodeInteger($value)); @@ -59,7 +46,8 @@ public function testEncodeInteger($value, $encoded) { /** * @expectedException InvalidArgumentException - * @covers PHP\BitTorrent\Encoder::encodeInteger + * @expectedExceptionMessage Expected an integer. + * @covers ::encodeInteger */ public function testEncodeNonIntegerAsInteger() { $this->encoder->encodeInteger('one'); @@ -71,16 +59,18 @@ public function testEncodeNonIntegerAsInteger() { * @return array[] */ public function getEncodeStringData() { - return array( - array('spam', '4:spam'), - array('foobar', '6:foobar'), - array('foo:bar', '7:foo:bar'), - ); + return [ + ['spam', '4:spam'], + ['foobar', '6:foobar'], + ['foo:bar', '7:foo:bar'], + ]; } /** - * @dataProvider getEncodeStringData() - * @covers PHP\BitTorrent\Encoder::encodeString + * @dataProvider getEncodeStringData + * @covers ::encodeString + * @param string $value + * @param string $encoded */ public function testEncodeString($value, $encoded) { $this->assertSame($encoded, $this->encoder->encodeString($value)); @@ -88,7 +78,8 @@ public function testEncodeString($value, $encoded) { /** * @expectedException InvalidArgumentException - * @covers PHP\BitTorrent\Encoder::encodeString + * @expectedExceptionMessage Expected string, got: integer. + * @covers ::encodeString */ public function testEncodeNonStringAsString() { $this->encoder->encodeString(1); @@ -100,74 +91,64 @@ public function testEncodeNonStringAsString() { * @return array[] */ public function getEncodeListData() { - return array( - array(array('spam', 1, array(1)), 'l4:spami1eli1eee'), - ); + return [ + [['spam', 1, [1]], 'l4:spami1eli1eee'], + ]; } /** - * @dataProvider getEncodeListData() - * @covers PHP\BitTorrent\Encoder::encodeList + * @dataProvider getEncodeListData + * @covers ::encodeList + * @param array $value + * @param string $encoded */ - public function testEncodeList($value, $encoded) { + public function testEncodeList(array $value, $encoded) { $this->assertSame($encoded, $this->encoder->encodeList($value)); } - /** - * @expectedException InvalidArgumentException - * @covers PHP\BitTorrent\Encoder::encodeList - */ - public function testEncodeNonListAsList() { - $this->encoder->encodeList(1); - } - /** * Data provider * * @return array[] */ public function getEncodeDictionaryData() { - return array( - array(array('1' => 'foo', 'foo' => 'bar', 'list' => array(1, 2, 3)), 'd3:foo3:bar4:listli1ei2ei3ee1:13:fooe'), - array(array('foo' => 'bar', 'spam' => 'eggs'), 'd3:foo3:bar4:spam4:eggse'), - array(array('spam' => 'eggs', 'foo' => 'bar'), 'd3:foo3:bar4:spam4:eggse'), - ); + return [ + [['1' => 'foo', 'foo' => 'bar', 'list' => [1, 2, 3]], 'd3:foo3:bar4:listli1ei2ei3ee1:13:fooe'], + [['foo' => 'bar', 'spam' => 'eggs'], 'd3:foo3:bar4:spam4:eggse'], + [['spam' => 'eggs', 'foo' => 'bar'], 'd3:foo3:bar4:spam4:eggse'], + ]; } /** - * @dataProvider getEncodeDictionaryData() - * @covers PHP\BitTorrent\Encoder::encodeDictionary + * @dataProvider getEncodeDictionaryData + * @covers ::encodeDictionary + * @param array $value + * @param string $encoded */ - public function testEncodeDictionary($value, $encoded) { + public function testEncodeDictionary(array $value, $encoded) { $this->assertSame($encoded, $this->encoder->encodeDictionary($value)); } - /** - * @expectedException InvalidArgumentException - * @covers PHP\BitTorrent\Encoder::encodeDictionary - */ - public function testEncodeDictionaryListAsDictionary() { - $this->encoder->encodeDictionary('foo'); - } - /** * Data provider * * @return array[] */ public function getEncodeData() { - return array( - array(1, 'i1e'), - array('spam', '4:spam'), - array(array(1, 2, 3), 'li1ei2ei3ee'), - array(array('foo' => 'bar', 'spam' => 'sucks'), 'd3:foo3:bar4:spam5:suckse'), - ); + return [ + [1, 'i1e'], + ['spam', '4:spam'], + [[1, 2, 3], 'li1ei2ei3ee'], + [['foo' => 'bar', 'spam' => 'sucks'], 'd3:foo3:bar4:spam5:suckse'], + ]; } /** - * @dataProvider getEncodeData() - * @covers PHP\BitTorrent\Encoder::encode - * @covers PHP\BitTorrent\Encoder::isInt + * @dataProvider getEncodeData + * @covers ::encode + * @covers ::isInt + * @param string|int|array $value + * @param string $encoded */ public function testEncodeUsingGenericMethod($value, $encoded) { $this->assertSame($encoded, $this->encoder->encode($value)); @@ -175,21 +156,23 @@ public function testEncodeUsingGenericMethod($value, $encoded) { /** * @expectedException InvalidArgumentException - * @covers PHP\BitTorrent\Encoder::encode + * @expectedExceptionMessage Variables of type object can not be encoded. + * @covers ::encode */ public function testEncodeNonSupportedType() { - $this->encoder->encode(new \stdClass()); + $this->encoder->encode(new stdClass()); } /** - * @covers PHP\BitTorrent\Encoder::encode - * @covers PHP\BitTorrent\Encoder::setParam + * @covers ::__construct + * @covers ::encode + * @covers ::setParam */ public function testCanEncodeEmptyArraysAsDictionaries() { - $this->assertSame('le', $this->encoder->encode(array())); + $this->assertSame('le', $this->encoder->encode([])); $this->assertSame($this->encoder, $this->encoder->setParam('encodeEmptyArrayAsDictionary', true)); - $this->assertSame('de', $this->encoder->encode(array())); + $this->assertSame('de', $this->encoder->encode([])); $this->assertSame($this->encoder, $this->encoder->setParam('encodeEmptyArrayAsDictionary', false)); - $this->assertSame('le', $this->encoder->encode(array())); + $this->assertSame('le', $this->encoder->encode([])); } } diff --git a/tests/TorrentTest.php b/tests/TorrentTest.php index ef96304..a575201 100644 --- a/tests/TorrentTest.php +++ b/tests/TorrentTest.php @@ -1,21 +1,12 @@ - * - * For the full copyright and license information, please view the LICENSE file that was - * distributed with this source code. - */ +namespace BitTorrent; -namespace PHP\BitTorrent; +use PHPUnit_Framework_TestCase; /** - * @package UnitTests - * @author Christer Edvartsen - * @covers PHP\BitTorrent\Torrent + * @coversDefaultClass BitTorrent\Torrent */ -class TorrentTest extends \PHPUnit_Framework_TestCase { +class TorrentTest extends PHPUnit_Framework_TestCase { /** * @var Torrent */ @@ -29,16 +20,9 @@ public function setUp() { } /** - * Tear down the torrent instance - */ - public function tearDown() { - $this->torrent = null; - } - - /** - * @covers PHP\BitTorrent\Torrent::__construct - * @covers PHP\BitTorrent\Torrent::setAnnounce - * @covers PHP\BitTorrent\Torrent::getAnnounce + * @covers ::__construct + * @covers ::setAnnounce + * @covers ::getAnnounce */ public function testConstructor() { $announce = 'http://tracker/'; @@ -47,8 +31,8 @@ public function testConstructor() { } /** - * @covers PHP\BitTorrent\Torrent::setComment - * @covers PHP\BitTorrent\Torrent::getComment + * @covers ::setComment + * @covers ::getComment */ public function testSetGetComment() { $comment = 'This is my comment'; @@ -57,8 +41,8 @@ public function testSetGetComment() { } /** - * @covers PHP\BitTorrent\Torrent::setCreatedBy - * @covers PHP\BitTorrent\Torrent::getCreatedBy + * @covers ::setCreatedBy + * @covers ::getCreatedBy */ public function testSetGetCreatedBy() { $createdBy = 'Some client name'; @@ -67,8 +51,8 @@ public function testSetGetCreatedBy() { } /** - * @covers PHP\BitTorrent\Torrent::setCreatedAt - * @covers PHP\BitTorrent\Torrent::getCreatedAt + * @covers ::setCreatedAt + * @covers ::getCreatedAt */ public function testSetGetCreationDate() { $timestamp = time(); @@ -77,8 +61,8 @@ public function testSetGetCreationDate() { } /** - * @covers PHP\BitTorrent\Torrent::setInfo - * @covers PHP\BitTorrent\Torrent::getInfo + * @covers ::setInfo + * @covers ::getInfo */ public function testSetGetInfo() { $info = array('some' => 'data'); @@ -87,8 +71,8 @@ public function testSetGetInfo() { } /** - * @covers PHP\BitTorrent\Torrent::setAnnounce - * @covers PHP\BitTorrent\Torrent::getAnnounce + * @covers ::setAnnounce + * @covers ::getAnnounce */ public function testSetGetAnnounce() { $announce = 'http://tracker/'; @@ -97,8 +81,8 @@ public function testSetGetAnnounce() { } /** - * @covers PHP\BitTorrent\Torrent::setAnnounceList - * @covers PHP\BitTorrent\Torrent::getAnnounceList + * @covers ::setAnnounceList + * @covers ::getAnnounceList */ public function testSetGetAnnounceList() { $announceList = array('http://tracker1/', 'http://tracker2/'); @@ -107,8 +91,8 @@ public function testSetGetAnnounceList() { } /** - * @covers PHP\BitTorrent\Torrent::setPieceLengthExp - * @covers PHP\BitTorrent\Torrent::getPieceLengthExp + * @covers ::setPieceLengthExp + * @covers ::getPieceLengthExp */ public function testSetGetPieceLengthExp() { $exp = 6; @@ -118,7 +102,7 @@ public function testSetGetPieceLengthExp() { /** * @expectedException RuntimeException - * @covers PHP\BitTorrent\Torrent::getName + * @covers ::getName */ public function testGetNameWithNoInfoBlockAdded() { $this->torrent->getName(); @@ -126,7 +110,7 @@ public function testGetNameWithNoInfoBlockAdded() { /** * @expectedException RuntimeException - * @covers PHP\BitTorrent\Torrent::getSize + * @covers ::getSize */ public function testGetSizeWithNoInfoBlockAdded() { $this->torrent->getSize(); @@ -134,15 +118,15 @@ public function testGetSizeWithNoInfoBlockAdded() { /** * @expectedException RuntimeException - * @covers PHP\BitTorrent\Torrent::getFileList + * @covers ::getFileList */ public function testGetFileListWithNoInfoBlockAdded() { $this->torrent->getFileList(); } /** - * @covers PHP\BitTorrent\Torrent::setInfo - * @covers PHP\BitTorrent\Torrent::getName + * @covers ::setInfo + * @covers ::getName */ public function testGetName() { $name = 'Some name'; @@ -152,8 +136,8 @@ public function testGetName() { } /** - * @covers PHP\BitTorrent\Torrent::setInfo - * @covers PHP\BitTorrent\Torrent::getSize + * @covers ::setInfo + * @covers ::getSize */ public function testGetSizeWhenLengthIsPresentInTheInfoBlock() { $length = 123; @@ -163,8 +147,8 @@ public function testGetSizeWhenLengthIsPresentInTheInfoBlock() { } /** - * @covers PHP\BitTorrent\Torrent::setInfo - * @covers PHP\BitTorrent\Torrent::getFileList + * @covers ::setInfo + * @covers ::getFileList */ public function testGetFileListWhenInfoBlockOnlyContainsOneFile() { $name = 'some_filename'; @@ -174,8 +158,8 @@ public function testGetFileListWhenInfoBlockOnlyContainsOneFile() { } /** - * @covers PHP\BitTorrent\Torrent::setInfo - * @covers PHP\BitTorrent\Torrent::getFileList + * @covers ::setInfo + * @covers ::getFileList */ public function testGetFileList() { $files = array( @@ -189,9 +173,9 @@ public function testGetFileList() { } /** - * @covers PHP\BitTorrent\Torrent::setInfo - * @covers PHP\BitTorrent\Torrent::getSize - * @covers PHP\BitTorrent\Torrent::add + * @covers ::setInfo + * @covers ::getSize + * @covers ::add */ public function testGetSizeWhenInfoBlockHasSeveralFiles() { $files = array( @@ -205,14 +189,14 @@ public function testGetSizeWhenInfoBlockHasSeveralFiles() { } /** - * @covers PHP\BitTorrent\Torrent::createFromTorrentFile - * @covers PHP\BitTorrent\Torrent::getAnnounce - * @covers PHP\BitTorrent\Torrent::getComment - * @covers PHP\BitTorrent\Torrent::getCreatedBy - * @covers PHP\BitTorrent\Torrent::getCreatedAt - * @covers PHP\BitTorrent\Torrent::getSize - * @covers PHP\BitTorrent\Torrent::add - * @covers PHP\BitTorrent\Torrent::getFileList + * @covers ::createFromTorrentFile + * @covers ::getAnnounce + * @covers ::getComment + * @covers ::getCreatedBy + * @covers ::getCreatedAt + * @covers ::getSize + * @covers ::add + * @covers ::getFileList */ public function testCreateFromTorrentFile() { $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/valid.torrent'); @@ -226,9 +210,9 @@ public function testCreateFromTorrentFile() { } /** - * @covers PHP\BitTorrent\Torrent::createFromTorrentFile - * @covers PHP\BitTorrent\Torrent::getAnnounce - * @covers PHP\BitTorrent\Torrent::getFileList + * @covers ::createFromTorrentFile + * @covers ::getAnnounce + * @covers ::getFileList */ public function testCreateFromTorrentFileWithLists() { $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_extra_files/extra.torrent'); @@ -248,8 +232,8 @@ public function testCreateFromTorrentFileWithLists() { } /** - * @covers PHP\BitTorrent\Torrent::createFromTorrentFile - * @covers PHP\BitTorrent\Torrent::getExtraMeta + * @covers ::createFromTorrentFile + * @covers ::getExtraMeta */ public function testCreateFromTorrentFileWithExtra() { $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_extra_files/extra.torrent'); @@ -267,12 +251,12 @@ public function testCreateFromTorrentFileWithExtra() { } /** - * @covers PHP\BitTorrent\Torrent::createFromPath - * @covers PHP\BitTorrent\Torrent::getAnnounce - * @covers PHP\BitTorrent\Torrent::getName - * @covers PHP\BitTorrent\Torrent::getSize - * @covers PHP\BitTorrent\Torrent::add - * @covers PHP\BitTorrent\Torrent::getFileList + * @covers ::createFromPath + * @covers ::getAnnounce + * @covers ::getName + * @covers ::getSize + * @covers ::add + * @covers ::getFileList */ public function testCreateFromPathWhenUsingADirectoryAsArgument() { $path = __DIR__ . '/_files'; @@ -286,12 +270,12 @@ public function testCreateFromPathWhenUsingADirectoryAsArgument() { } /** - * @covers PHP\BitTorrent\Torrent::createFromPath - * @covers PHP\BitTorrent\Torrent::getAnnounce - * @covers PHP\BitTorrent\Torrent::getName - * @covers PHP\BitTorrent\Torrent::getSize - * @covers PHP\BitTorrent\Torrent::add - * @covers PHP\BitTorrent\Torrent::getFileList + * @covers ::createFromPath + * @covers ::getAnnounce + * @covers ::getName + * @covers ::getSize + * @covers ::add + * @covers ::getFileList */ public function testCreateFromPathWhenUsingAFileAsArgument() { $path = __DIR__ . '/_files/valid.torrent'; @@ -305,21 +289,21 @@ public function testCreateFromPathWhenUsingAFileAsArgument() { } /** - * @covers PHP\BitTorrent\Torrent::createFromPath - * @covers PHP\BitTorrent\Torrent::setComment - * @covers PHP\BitTorrent\Torrent::setCreatedBy - * @covers PHP\BitTorrent\Torrent::setAnnounceList - * @covers PHP\BitTorrent\Torrent::save - * @covers PHP\BitTorrent\Torrent::createFromTorrentFile - * @covers PHP\BitTorrent\Torrent::getAnnounce - * @covers PHP\BitTorrent\Torrent::getComment - * @covers PHP\BitTorrent\Torrent::getCreatedBy - * @covers PHP\BitTorrent\Torrent::getName - * @covers PHP\BitTorrent\Torrent::getSize - * @covers PHP\BitTorrent\Torrent::add - * @covers PHP\BitTorrent\Torrent::getFileList - * @covers PHP\BitTorrent\Torrent::getAnnounceList - * @covers PHP\BitTorrent\Torrent::getInfoPart + * @covers ::createFromPath + * @covers ::setComment + * @covers ::setCreatedBy + * @covers ::setAnnounceList + * @covers ::save + * @covers ::createFromTorrentFile + * @covers ::getAnnounce + * @covers ::getComment + * @covers ::getCreatedBy + * @covers ::getName + * @covers ::getSize + * @covers ::add + * @covers ::getFileList + * @covers ::getAnnounceList + * @covers ::getInfoPart */ public function testSaveTorrent() { $path = __DIR__ . '/_files'; @@ -355,54 +339,11 @@ public function testSaveTorrent() { } /** - * @covers PHP\BitTorrent\Torrent::createFromPath - * @covers PHP\BitTorrent\Torrent::setComment - * @covers PHP\BitTorrent\Torrent::setCreatedBy - * @covers PHP\BitTorrent\Torrent::setAnnounceList - * @covers PHP\BitTorrent\Torrent::save - * @covers PHP\BitTorrent\Torrent::createFromTorrentFile - * @covers PHP\BitTorrent\Torrent::getComment - * @covers PHP\BitTorrent\Torrent::getCreatedBy - * @covers PHP\BitTorrent\Torrent::getName - * @covers PHP\BitTorrent\Torrent::getSize - * @covers PHP\BitTorrent\Torrent::add - * @covers PHP\BitTorrent\Torrent::getFileList - * @covers PHP\BitTorrent\Torrent::getInfoPart - */ - public function testSaveTrackerlessTorrent() { - $path = __DIR__ . '/_files'; - $comment = 'Some comment'; - $createdBy = 'PHPUnit'; - $target = tempnam(sys_get_temp_dir(), 'PHP\BitTorrent'); - - if (!$target) { - $this->fail('Could not create file: ' . $target); - } - - $torrent = Torrent::createFromPath($path); - $torrent->setComment($comment) - ->setCreatedBy($createdBy) - ->save($target); - - // Now load the file and make sure the values are correct - $torrent = Torrent::createFromTorrentFile($target); - - $this->assertSame($comment, $torrent->getComment()); - $this->assertSame($createdBy, $torrent->getCreatedBy()); - $this->assertSame('_files', $torrent->getName()); - $this->assertEquals(902910, $torrent->getSize()); - $this->assertSame(7, count($torrent->getFileList())); - - // Remove the saved file - unlink($target); - } - - /** - * @covers PHP\BitTorrent\Torrent::createFromPath - * @covers PHP\BitTorrent\Torrent::setExtraMeta - * @covers PHP\BitTorrent\Torrent::save - * @covers PHP\BitTorrent\Torrent::createFromTorrentFile - * @covers PHP\BitTorrent\Torrent::getExtraMeta + * @covers ::createFromPath + * @covers ::setExtraMeta + * @covers ::save + * @covers ::createFromTorrentFile + * @covers ::getExtraMeta */ public function testSaveWithExtra() { $path = __DIR__ . '/_files'; @@ -440,9 +381,9 @@ public function testSaveWithExtra() { * * @expectedException RuntimeException * @expectedExceptionMessage Duplicate key in extra meta info - * @covers PHP\BitTorrent\Torrent::createFromPath - * @covers PHP\BitTorrent\Torrent::setExtraMeta - * @covers PHP\BitTorrent\Torrent::save + * @covers ::createFromPath + * @covers ::setExtraMeta + * @covers ::save */ public function testSaveWithInvalidExtra() { $path = __DIR__ . '/_files'; @@ -463,12 +404,26 @@ public function testSaveWithInvalidExtra() { unlink($target); } + /** + * Try to save when no announce has been given. The code we are testing is AFTER the code that + * checks if the file specified is writeable, so make sure the argument to save() is a file that + * is writeable. + * + * @expectedException RuntimeException + * @expectedExceptionMessage Announce URL is missing + * @covers ::save + */ + public function testSaveWithNoAnnounce() { + $target = tempnam(sys_get_temp_dir(), 'PHP\BitTorrent'); + $this->torrent->save($target); + } + /** * @expectedException RuntimeException * @expectedExceptionMessage The info part of the torrent is not set. - * @covers PHP\BitTorrent\Torrent::setAnnounce - * @covers PHP\BitTorrent\Torrent::save - * @covers PHP\BitTorrent\Torrent::getInfoPart + * @covers ::setAnnounce + * @covers ::save + * @covers ::getInfoPart */ public function testSaveWithNoInfoBlock() { $target = tempnam(sys_get_temp_dir(), 'PHP\BitTorrent'); @@ -479,8 +434,8 @@ public function testSaveWithNoInfoBlock() { /** * @expectedException InvalidArgumentException * @expectedExceptionMessage Could not open file - * @covers PHP\BitTorrent\Torrent::createFromPath - * @covers PHP\BitTorrent\Torrent::save + * @covers ::createFromPath + * @covers ::save */ public function testSaveToUnwritableFile() { $target = uniqid() . DIRECTORY_SEPARATOR . uniqid(); @@ -492,7 +447,7 @@ public function testSaveToUnwritableFile() { /** * @expectedException InvalidArgumentException * @expectedExceptionMessage foobar does not exist - * @covers PHP\BitTorrent\Torrent::createFromTorrentFile + * @covers ::createFromTorrentFile */ public function testCreateFromTorrentFileWithUnexistingTorrentFile() { Torrent::createFromTorrentFile('foobar'); @@ -501,7 +456,7 @@ public function testCreateFromTorrentFileWithUnexistingTorrentFile() { /** * @expectedException InvalidArgumentException * @expectedExceptionMessage Invalid path: foobar - * @covers PHP\BitTorrent\Torrent::createFromPath + * @covers ::createFromPath */ public function testCreateFromPathWithInvalidPath() { Torrent::createFromPath('foobar', 'http://trackerurl'); @@ -509,7 +464,7 @@ public function testCreateFromPathWithInvalidPath() { /** * @expectedException RuntimeException - * @covers PHP\BitTorrent\Torrent::getHash + * @covers ::getHash */ public function testThrowsExceptionWhenTryingToGenerateHashWithEmptyTorrentFile() { $this->torrent->getHash(); @@ -517,14 +472,14 @@ public function testThrowsExceptionWhenTryingToGenerateHashWithEmptyTorrentFile( /** * @expectedException RuntimeException - * @covers PHP\BitTorrent\Torrent::getEncodedHash + * @covers ::getEncodedHash */ public function testThrowsExceptionWhenTryingToGenerateEncodedHashWithEmptyTorrentFile() { $this->torrent->getEncodedHash(); } /** - * @covers PHP\BitTorrent\Torrent::getHash + * @covers ::getHash */ public function testGetHash() { $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/valid.torrent'); @@ -532,8 +487,8 @@ public function testGetHash() { } /** - * @covers PHP\BitTorrent\Torrent::getEncodedHash - * @covers PHP\BitTorrent\Torrent::getHash + * @covers ::getEncodedHash + * @covers ::getHash */ public function testGetEncodedHash() { $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/valid.torrent'); @@ -541,8 +496,8 @@ public function testGetEncodedHash() { } /** - * @covers PHP\BitTorrent\Torrent::getSize - * @covers PHP\BitTorrent\Torrent::add + * @covers ::getSize + * @covers ::add */ public function testGetSizeWithLargeValues() { $torrent1 = Torrent::createFromTorrentFile(__DIR__ . '/_files/large_files.torrent'); @@ -553,7 +508,7 @@ public function testGetSizeWithLargeValues() { } /** - * @covers PHP\BitTorrent\Torrent::isPrivate + * @covers ::isPrivate */ public function testIsPrivateWhenFlagDoesNotExist() { $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/large_files.torrent'); @@ -562,7 +517,7 @@ public function testIsPrivateWhenFlagDoesNotExist() { } /** - * @covers PHP\BitTorrent\Torrent::isPrivate + * @covers ::isPrivate */ public function testIsPrivateWhenItExistsAndIs1() { $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/file_with_private_set_to_1.torrent'); @@ -571,7 +526,7 @@ public function testIsPrivateWhenItExistsAndIs1() { } /** - * @covers PHP\BitTorrent\Torrent::isPrivate + * @covers ::isPrivate */ public function testIsPrivateWhenItExistsAndIsNot1() { $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/file_with_private_set_to_0.torrent'); From 78d408aac6f3b509cbfcf856cc3224814a454312 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 19:06:53 +0100 Subject: [PATCH 23/70] Bump year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 28f18a2..df2fecf 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ PHP BitTorrent -Copyright (c) 2011-2013, Christer Edvartsen +Copyright (c) 2011-2016, Christer Edvartsen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to From 2f92f4ebae0025b2e89e63960cb10ec828e5a0cd Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 19:07:07 +0100 Subject: [PATCH 24/70] Add note regarding license --- README.markdown | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.markdown b/README.markdown index 2482b1e..70d015c 100644 --- a/README.markdown +++ b/README.markdown @@ -108,3 +108,8 @@ On 32-bit platforms these components work slightly different with regards to int * The generic `BitTorrent\Encoder::encode` method will encode both integers and strings containing numerics as strings (strings containing floating point values are still treated as regular strings). * The `BitTorrent\Decoder::decodeInteger` method will return values as strings, and not integers. * The `BitTorrent\Torrent::getSize` method will use the [bcadd](http://no2.php.net/manual/en/function.bcadd.php) function to calculate the size of the files in the torrent. + +## License +Licensed under the MIT License. + +See [LICENSE](LICENSE) file. From 107a3ecbd26c880e4a47faf5b13485fb1d983d4c Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 19:07:21 +0100 Subject: [PATCH 25/70] Fix some comments and old style array notation --- src/Decoder.php | 27 ++++++--------------------- src/DecoderInterface.php | 31 ++++++++----------------------- src/Encoder.php | 19 ++----------------- src/EncoderInterface.php | 15 --------------- src/Torrent.php | 18 ------------------ 5 files changed, 16 insertions(+), 94 deletions(-) diff --git a/src/Decoder.php b/src/Decoder.php index 9ee7eb2..8ab49e9 100644 --- a/src/Decoder.php +++ b/src/Decoder.php @@ -1,23 +1,8 @@ - * - * For the full copyright and license information, please view the LICENSE file that was - * distributed with this source code. - */ - namespace BitTorrent; use InvalidArgumentException; -/** - * Decode bittorrent strings to it's PHP variable counterpart - * - * @package Decoder - * @author Christer Edvartsen - */ class Decoder implements DecoderInterface { /** * Encoder instance @@ -50,10 +35,10 @@ public function decodeFile($file, $strict = false) { $dictionary = $this->decodeDictionary(file_get_contents($file, true)); if ($strict) { - if (!isset($dictionary['announce']) || !is_string($dictionary['announce'])) { - throw new InvalidArgumentException('Missing "announce" key.'); - } else if (!isset($dictionary['info']) || !is_array($dictionary['info'])) { - throw new InvalidArgumentException('Missing "info" key.'); + if (!isset($dictionary['announce']) || !is_string($dictionary['announce']) && !empty($dictionary['announce'])) { + throw new InvalidArgumentException('Missing or empty "announce" key.'); + } else if (!isset($dictionary['info']) || !is_array($dictionary['info']) && !empty($dictionary['info'])) { + throw new InvalidArgumentException('Missing or empty "info" key.'); } } @@ -131,7 +116,7 @@ public function decodeList($list) { throw new InvalidArgumentException('Parameter is not an encoded list.'); } - $ret = array(); + $ret = []; $length = strlen($list); $i = 1; @@ -159,7 +144,7 @@ public function decodeDictionary($dictionary) { } $length = strlen($dictionary); - $ret = array(); + $ret = []; $i = 1; while ($i < $length) { diff --git a/src/DecoderInterface.php b/src/DecoderInterface.php index 2a7baf8..8c17ffc 100644 --- a/src/DecoderInterface.php +++ b/src/DecoderInterface.php @@ -1,23 +1,8 @@ - * - * For the full copyright and license information, please view the LICENSE file that was - * distributed with this source code. - */ - namespace BitTorrent; use InvalidArgumentException; -/** - * Interface for decoders - * - * @package Decoder - * @author Christer Edvartsen - */ interface DecoderInterface { /** * Decode a file @@ -28,13 +13,13 @@ interface DecoderInterface { * - announce * - info * - * Pr. default the method does not check for these elements. + * By default the method does not check for these elements. * * @param string $file Path to the torrent file we want to decode * @param boolean $strict If set to true this method will check for certain elements in the * dictionary. * @return array Returns the decoded version of the file as an array - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ function decodeFile($file, $strict = false); @@ -43,16 +28,16 @@ function decodeFile($file, $strict = false); * * @param string $string The string to decode * @return int|string|array Returns the native PHP counterpart of the encoded string - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ function decode($string); /** - * Decode a encoded PHP integer + * Decode an encoded PHP integer * * @param string $integer The integer to decode * @return int|string Returns the decoded integer (as a string on 32-bit platforms) - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ function decodeInteger($integer); @@ -61,7 +46,7 @@ function decodeInteger($integer); * * @param string $string The string to decode * @return string Returns the decoded string value - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ function decodeString($string); @@ -70,7 +55,7 @@ function decodeString($string); * * @param string $list Encoded list * @return array Returns a numerical array - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ function decodeList($list); @@ -79,7 +64,7 @@ function decodeList($list); * * @param string $dictionary Encoded dictionary * @return array Returns an associative array - * @throws \InvalidArgumentException + * @throws InvalidArgumentException */ function decodeDictionary($dictionary); } diff --git a/src/Encoder.php b/src/Encoder.php index 2c9b309..bd75caa 100644 --- a/src/Encoder.php +++ b/src/Encoder.php @@ -1,33 +1,18 @@ - * - * For the full copyright and license information, please view the LICENSE file that was - * distributed with this source code. - */ - namespace BitTorrent; use InvalidArgumentException; -/** - * Encode encodable PHP variables to the BitTorrent counterpart - * - * @package Encoder - * @author Christer Edvartsen - */ class Encoder implements EncoderInterface { /** * Parameters for the encoder * * @var array */ - private $params = array( + private $params = [ // Set to true to encode empty arrays as dictionaries ("de") instead of lists ("le") 'encodeEmptyArrayAsDictionary' => false, - ); + ]; /** * Class constructor diff --git a/src/EncoderInterface.php b/src/EncoderInterface.php index 5846d2a..b660775 100644 --- a/src/EncoderInterface.php +++ b/src/EncoderInterface.php @@ -1,23 +1,8 @@ - * - * For the full copyright and license information, please view the LICENSE file that was - * distributed with this source code. - */ - namespace BitTorrent; use InvalidArgumentException; -/** - * Interface for encoders - * - * @package Encoder - * @author Christer Edvartsen - */ interface EncoderInterface { /** * Set a parameter diff --git a/src/Torrent.php b/src/Torrent.php index 82fb6cd..8b35966 100644 --- a/src/Torrent.php +++ b/src/Torrent.php @@ -1,13 +1,4 @@ - * - * For the full copyright and license information, please view the LICENSE file that was - * distributed with this source code. - */ - namespace BitTorrent; use RecursiveDirectoryIterator; @@ -15,15 +6,6 @@ use RuntimeException; use InvalidArgumentException; -/** - * A class that represents a single torrent file - * - * This class represents a torrent file. It also has methods for loading from a torrent file, and - * loading from a directory or a single file. - * - * @package Torrent - * @author Christer Edvartsen - */ class Torrent { /** * The exponent to use when making the pieces From 46d2f732df14750359759bdbab18b058a4aa5bca Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 19:38:58 +0100 Subject: [PATCH 26/70] Remove the setParam method --- src/Encoder.php | 9 --------- src/EncoderInterface.php | 9 --------- tests/DecoderTest.php | 4 ++-- tests/EncoderTest.php | 13 +++++++------ 4 files changed, 9 insertions(+), 26 deletions(-) diff --git a/src/Encoder.php b/src/Encoder.php index bd75caa..945b37a 100644 --- a/src/Encoder.php +++ b/src/Encoder.php @@ -23,15 +23,6 @@ public function __construct(array $params = []) { $this->params = array_replace($this->params, $params); } - /** - * {@inheritdoc} - */ - public function setParam($key, $value) { - $this->params[$key] = $value; - - return $this; - } - /** * {@inheritdoc} */ diff --git a/src/EncoderInterface.php b/src/EncoderInterface.php index b660775..c2aa588 100644 --- a/src/EncoderInterface.php +++ b/src/EncoderInterface.php @@ -4,15 +4,6 @@ use InvalidArgumentException; interface EncoderInterface { - /** - * Set a parameter - * - * @param string $key The key to set - * @param mixed $value The value to set - * @return EncoderInterface - */ - function setParam($key, $value); - /** * Encode any encodable variable * diff --git a/tests/DecoderTest.php b/tests/DecoderTest.php index 7a8a6c7..bd1cf97 100644 --- a/tests/DecoderTest.php +++ b/tests/DecoderTest.php @@ -221,7 +221,7 @@ public function testGenericDecodeWithInvalidData() { /** * @expectedException InvalidArgumentException - * @expectedExceptionMessage Missing "announce" key + * @expectedExceptionMessage Missing or empty "announce" key. * @covers ::decodeFile */ public function testDecodeTorrentFileStrictWithMissingAnnounce() { @@ -230,7 +230,7 @@ public function testDecodeTorrentFileStrictWithMissingAnnounce() { /** * @expectedException InvalidArgumentException - * @expectedExceptionMessage Missing "info" key + * @expectedExceptionMessage Missing or empty "info" key. * @covers ::decodeFile */ public function testDecodeTorrentFileStrictWithMissingInfo() { diff --git a/tests/EncoderTest.php b/tests/EncoderTest.php index d8836cf..6c0e8cd 100644 --- a/tests/EncoderTest.php +++ b/tests/EncoderTest.php @@ -166,13 +166,14 @@ public function testEncodeNonSupportedType() { /** * @covers ::__construct * @covers ::encode - * @covers ::setParam */ public function testCanEncodeEmptyArraysAsDictionaries() { - $this->assertSame('le', $this->encoder->encode([])); - $this->assertSame($this->encoder, $this->encoder->setParam('encodeEmptyArrayAsDictionary', true)); - $this->assertSame('de', $this->encoder->encode([])); - $this->assertSame($this->encoder, $this->encoder->setParam('encodeEmptyArrayAsDictionary', false)); - $this->assertSame('le', $this->encoder->encode([])); + $encoder = new Encoder(); + $this->assertSame('le', $encoder->encode([])); + + $encoder = new Encoder([ + 'encodeEmptyArrayAsDictionary' => true, + ]); + $this->assertSame('de', $encoder->encode([])); } } From ff827cff092a046f62e8f86d12325d7bce27224d Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Sun, 18 Dec 2016 20:15:53 +0100 Subject: [PATCH 27/70] Add type hint --- src/Torrent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Torrent.php b/src/Torrent.php index 8b35966..7ec41d7 100644 --- a/src/Torrent.php +++ b/src/Torrent.php @@ -351,7 +351,7 @@ public function getAnnounce() { * @param array $announceList The array of URLs to set * @return Torrent Returns self for a fluent interface */ - public function setAnnounceList($announceList) { + public function setAnnounceList(array $announceList) { $this->announceList = $announceList; return $this; From 296a81ae4561fbc4625a8fa6b7892cce75bd3800 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Thu, 23 May 2019 19:47:10 +0200 Subject: [PATCH 28/70] Bump PHP requirement to 7.1 and update PHPUnit --- .travis.yml | 4 +- ChangeLog.markdown | 48 --- README.markdown | 115 ------- composer.json | 16 +- composer.lock | 739 ++++++++++++++++++++++++++---------------- tests/DecoderTest.php | 4 +- tests/EncoderTest.php | 4 +- tests/TorrentTest.php | 4 +- 8 files changed, 469 insertions(+), 465 deletions(-) delete mode 100644 ChangeLog.markdown delete mode 100644 README.markdown diff --git a/.travis.yml b/.travis.yml index 66f2f93..ae99eb9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: php php: - - 5.6 - - 7.0 + - 7.2 + - 7.3 before_script: - composer self-update diff --git a/ChangeLog.markdown b/ChangeLog.markdown deleted file mode 100644 index 0d55aae..0000000 --- a/ChangeLog.markdown +++ /dev/null @@ -1,48 +0,0 @@ -Changelog for PHP BitTorrent -===================== - -Version 2.0.0 -------------- -__N/A__ - -* Bump PHP requirement from 5.3 to 5.6 -* Change namespace from PHP\BitTorrent to BitTorrent -* Added method to check if the torrent is private (@stormwalkerec) - -Version 1.1.0 -------------- -__2013-01-11__ - -* Added parameters for the Encoder. The only parameter currently used it "encodeEmptyArrayAsDictionary" which will cause the encoder to encode empty arrays as "de" (empty dictionary) instead of "le" (empty list). - -Version 1.0.0 -------------- -__2013-01-05__ - -* Introduced a getEncodedHash method in the Torrent component to get the URL-encoded hash (Daniel Espendiller) -* Fix issue with integer overflow on 32-bit platforms -* Added method to get the hash of the torrent file (Daniel Espendiller) -* Dictionaries are now sorted by keys before they are encoded (as specified in in http://bittorrent.org/beps/bep\_0003.html) - -Version 0.3.0 -------------- -__2012-12-08__ - -* Fixed parse error in composer.json (Daniel Espendiller) -* Added interfaces for the encoder and the decoder (Matt Drollette) -* Fixed autoloader issues in composer.json (Matt Drollette) -* Library is from now on available as a PHAR archive as well -* Allow getting/setting extra fields from the torrent meta data (Matt Drollette) - -Version 0.2.0 -------------- -__2012-01-04__ - -* Use proper namespaces -* Changed API to use instance methods instead of static methods - -Version 0.0.1 -------------- -__2011-01-29__ - -* Initial release diff --git a/README.markdown b/README.markdown deleted file mode 100644 index 70d015c..0000000 --- a/README.markdown +++ /dev/null @@ -1,115 +0,0 @@ -# PHP BitTorrent -**PHP BitTorrent** is a set of components that can be used to interact with torrent files (read+write) and encode/decode to/from the BitTorrent format. - -[![Current Build Status](https://secure.travis-ci.org/christeredvartsen/php-bittorrent.png)](http://travis-ci.org/christeredvartsen/php-bittorrent) - -## Requirements -PHP BitTorrent requires PHP 5.6 or above. - -## Installation -PHP BitTorrent can be installed using [Composer](https://getcomposer.org): - -```json -{ - "require": { - "christeredvartsen/php-bittorrent": "^2.0" - } -} -``` - -## Using the PHP BitTorrent API -### Encode PHP variables - -```php -encodeString('Some string')); // string(14) "11:Some string" -var_dump($encoder->encodeInteger(42)); // int(42) -var_dump($encoder->encodeList([1, 2, 3]); // string(11) "li1ei2ei3ee" -var_dump($encoder->encodeDictionary(['foo' => 'bar', 'bar' => 'foo']); // string(22) "d3:foo3:bar3:bar3:fooe" -``` - -There is also a convenience method simply called `encode` in the `BitTorrent\Encoder` class that can be used to encode all encodable variables (integers, strings and arrays). - -### Decode BitTorrent encoded data - -```php -decodeString('11:Some string')); // string(11) "Some string" -var_dump($decoder->decodeInteger('i42e')); // int(42) -var_dump($decoder->decodeList('li1ei2ei3ee'); // array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) } -var_dump($decoder->decodeDictionary('d3:foo3:bar3:bar3:fooe'); // array(2) { ["foo"]=> string(3) "bar" ["bar"]=> string(3) "foo" } -``` - -There is also a convenience method called `decode` that can decode any BitTorrent encoded data. - -### Decode torrent files - -The decoder class also has a method for decoding a torrent file (which is an encoded dictionary): - -```php -decodeFile('/path/to/file.torrent'); -``` - -### Create new torrent files and open existing ones - -The `BitTorrent\Torrent` class represents a torrent file and can be used to create torrent files. - -```php -setComment('Some comment') - ->save('/save/to/path/file.torrent'); -``` - -The class can also load a torrent file: - -```php -setAnnounce('http://tracker/announce.php') // Override announce in original file - ->setComment('Some comment') // Override commend in original file - ->save('/save/to/path/file.torrent'); // Save to a new file -``` - -### 32-bit platforms - -On 32-bit platforms these components work slightly different with regards to integers: - -* The generic `BitTorrent\Encoder::encode` method will encode both integers and strings containing numerics as strings (strings containing floating point values are still treated as regular strings). -* The `BitTorrent\Decoder::decodeInteger` method will return values as strings, and not integers. -* The `BitTorrent\Torrent::getSize` method will use the [bcadd](http://no2.php.net/manual/en/function.bcadd.php) function to calculate the size of the files in the torrent. - -## License -Licensed under the MIT License. - -See [LICENSE](LICENSE) file. diff --git a/composer.json b/composer.json index 8cfc840..0a5259c 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,10 @@ "name": "christeredvartsen/php-bittorrent", "type": "library", "description": "PHP BitTorrent is a set of components that can be used to interact with torrent files (read+write) and classes that can encode/decode to/from the BitTorrent format.", - "keywords": ["bittorrent", "torrent"], + "keywords": [ + "bittorrent", + "torrent" + ], "homepage": "https://github.com/christeredvartsen/php-bittorrent", "license": "MIT", "authors": [ @@ -12,10 +15,10 @@ } ], "require": { - "php": ">=5.6.0" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^5.7" + "phpunit/phpunit": "^7.0" }, "support": { "source": "https://github.com/christeredvartsen/php-bittorrent", @@ -38,9 +41,10 @@ "mkdir build", "mkdir build/coverage" ], - "test-phpunit": "vendor/bin/phpunit --verbose", + "test:phpunit": "vendor/bin/phpunit --verbose", + "test:phpunit:coverage": "vendor/bin/phpunit --verbose --coverage-html build/coverage", "test": [ - "@test-phpunit" + "@test:phpunit" ] } -} +} \ No newline at end of file diff --git a/composer.lock b/composer.lock index 8ba09ab..8a6a641 100644 --- a/composer.lock +++ b/composer.lock @@ -4,38 +4,39 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "2f47f1c31a1053b0bcbc924d5f3657ae", - "content-hash": "6bb05ab3786a98c7cf5ce2d4b7616823", + "content-hash": "a8fc0535bffbadc20d4b5becafb86b14", "packages": [], "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.0.5", + "version": "1.2.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" + "reference": "a2c590166b2133a4633738648b6b064edae0814a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", - "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a", + "reference": "a2c590166b2133a4633738648b6b064edae0814a", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "php": "^7.1" }, "require-dev": { - "athletic/athletic": "~0.1.8", + "doctrine/coding-standard": "^6.0", "ext-pdo": "*", "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { @@ -55,46 +56,52 @@ } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ "constructor", "instantiate" ], - "time": "2015-06-14 21:17:01" + "time": "2019-03-17T17:37:11+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.5.5", + "version": "1.9.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108" + "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/399c1f9781e222f6eb6cc238796f5200d1b7f108", - "reference": "399c1f9781e222f6eb6cc238796f5200d1b7f108", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", + "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", "shasum": "" }, "require": { - "php": ">=5.4.0" + "php": "^7.1" + }, + "replace": { + "myclabs/deep-copy": "self.version" }, "require-dev": { - "doctrine/collections": "1.*", - "phpunit/phpunit": "~4.1" + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^7.1" }, "type": "library", "autoload": { "psr-4": { "DeepCopy\\": "src/DeepCopy/" - } + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "Create deep copies (clones) of your objects", - "homepage": "https://github.com/myclabs/DeepCopy", "keywords": [ "clone", "copy", @@ -102,20 +109,122 @@ "object", "object graph" ], - "time": "2016-10-31 17:19:45" + "time": "2019-04-07T13:18:21+00:00" + }, + { + "name": "phar-io/manifest", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "reference": "7761fcacf03b4d4f16e7ccb606d4879ca431fcf4", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "phar-io/version": "^2.0", + "php": "^5.6 || ^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "time": "2018-07-08T19:23:20+00:00" + }, + { + "name": "phar-io/version", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "reference": "45a2ec53a73c70ce41d55cedef9063630abaf1b6", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "time": "2018-07-08T19:19:57+00:00" }, { "name": "phpdocumentor/reflection-common", - "version": "1.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c" + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c", - "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", "shasum": "" }, "require": { @@ -156,33 +265,39 @@ "reflection", "static analysis" ], - "time": "2015-12-27 11:43:31" + "time": "2017-09-11T18:02:19+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "3.1.1", + "version": "4.3.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" + "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", + "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", "shasum": "" }, "require": { - "php": ">=5.5", - "phpdocumentor/reflection-common": "^1.0@dev", - "phpdocumentor/type-resolver": "^0.2.0", + "php": "^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", "webmozart/assert": "^1.0" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^4.4" + "doctrine/instantiator": "~1.0.5", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^6.4" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + } + }, "autoload": { "psr-4": { "phpDocumentor\\Reflection\\": [ @@ -201,24 +316,24 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2016-09-30 07:12:33" + "time": "2019-04-30T17:48:53+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "0.2.1", + "version": "0.4.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", - "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", "shasum": "" }, "require": { - "php": ">=5.5", + "php": "^5.5 || ^7.0", "phpdocumentor/reflection-common": "^1.0" }, "require-dev": { @@ -248,37 +363,37 @@ "email": "me@mikevanriel.com" } ], - "time": "2016-11-25 06:54:22" + "time": "2017-07-14T14:27:02+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.6.2", + "version": "1.8.0", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb" + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/6c52c2722f8460122f96f86346600e1077ce22cb", - "reference": "6c52c2722f8460122f96f86346600e1077ce22cb", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1", - "sebastian/recursion-context": "^1.0|^2.0" + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" }, "require-dev": { - "phpspec/phpspec": "^2.0", - "phpunit/phpunit": "^4.8 || ^5.6.5" + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.8.x-dev" } }, "autoload": { @@ -311,44 +426,44 @@ "spy", "stub" ], - "time": "2016-11-21 14:58:47" + "time": "2018-08-05T17:53:17+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "4.0.3", + "version": "6.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "903fd6318d0a90b4770a009ff73e4a4e9c437929" + "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/903fd6318d0a90b4770a009ff73e4a4e9c437929", - "reference": "903fd6318d0a90b4770a009ff73e4a4e9c437929", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0", - "phpunit/php-file-iterator": "~1.3", - "phpunit/php-text-template": "~1.2", - "phpunit/php-token-stream": "^1.4.2", - "sebastian/code-unit-reverse-lookup": "~1.0", - "sebastian/environment": "^1.3.2 || ^2.0", - "sebastian/version": "~1.0|~2.0" + "ext-dom": "*", + "ext-xmlwriter": "*", + "php": "^7.1", + "phpunit/php-file-iterator": "^2.0", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-token-stream": "^3.0", + "sebastian/code-unit-reverse-lookup": "^1.0.1", + "sebastian/environment": "^3.1 || ^4.0", + "sebastian/version": "^2.0.1", + "theseer/tokenizer": "^1.1" }, "require-dev": { - "ext-xdebug": ">=2.1.4", - "phpunit/phpunit": "^5.4" + "phpunit/phpunit": "^7.0" }, "suggest": { - "ext-dom": "*", - "ext-xdebug": ">=2.4.0", - "ext-xmlwriter": "*" + "ext-xdebug": "^2.6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0.x-dev" + "dev-master": "6.1-dev" } }, "autoload": { @@ -363,7 +478,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -374,29 +489,32 @@ "testing", "xunit" ], - "time": "2016-11-28 16:00:31" + "time": "2018-10-31T16:06:48+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.2", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" + "reference": "050bedf145a257b1ff02746c31894800e5122946" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946", + "reference": "050bedf145a257b1ff02746c31894800e5122946", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -411,7 +529,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -421,7 +539,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03 07:40:28" + "time": "2018-09-13T20:33:42+00:00" }, { "name": "phpunit/php-text-template", @@ -462,29 +580,34 @@ "keywords": [ "template" ], - "time": "2015-06-21 13:50:34" + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", - "version": "1.0.8", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" + "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", - "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b389aebe1b8b0578430bda0c7c95a829608e059", + "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "~4|~5" + "phpunit/phpunit": "^7.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, "autoload": { "classmap": [ "src/" @@ -497,7 +620,7 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], @@ -506,33 +629,33 @@ "keywords": [ "timer" ], - "time": "2016-05-12 18:03:57" + "time": "2019-02-20T10:12:59+00:00" }, { "name": "phpunit/php-token-stream", - "version": "1.4.9", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b" + "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3b402f65a4cc90abf6e1104e388b896ce209631b", - "reference": "3b402f65a4cc90abf6e1104e388b896ce209631b", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18", + "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.3.3" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -555,55 +678,57 @@ "keywords": [ "tokenizer" ], - "time": "2016-11-15 14:06:22" + "time": "2018-10-30T05:52:18+00:00" }, { "name": "phpunit/phpunit", - "version": "5.7.4", + "version": "7.5.11", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "af91da3f2671006ff5d0628023de3b7ac4d1ef09" + "reference": "64cb33f5b520da490a7b13149d39b43cf3c890c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/af91da3f2671006ff5d0628023de3b7ac4d1ef09", - "reference": "af91da3f2671006ff5d0628023de3b7ac4d1ef09", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/64cb33f5b520da490a7b13149d39b43cf3c890c6", + "reference": "64cb33f5b520da490a7b13149d39b43cf3c890c6", "shasum": "" }, "require": { + "doctrine/instantiator": "^1.1", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", - "myclabs/deep-copy": "~1.3", - "php": "^5.6 || ^7.0", - "phpspec/prophecy": "^1.6.2", - "phpunit/php-code-coverage": "^4.0.3", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "^3.2", - "sebastian/comparator": "~1.2.2", - "sebastian/diff": "~1.2", - "sebastian/environment": "^1.3.4 || ^2.0", - "sebastian/exporter": "~2.0", - "sebastian/global-state": "^1.0 || ^2.0", - "sebastian/object-enumerator": "~2.0", - "sebastian/resource-operations": "~1.0", - "sebastian/version": "~1.0|~2.0", - "symfony/yaml": "~2.1|~3.0" + "myclabs/deep-copy": "^1.7", + "phar-io/manifest": "^1.0.2", + "phar-io/version": "^2.0", + "php": "^7.1", + "phpspec/prophecy": "^1.7", + "phpunit/php-code-coverage": "^6.0.7", + "phpunit/php-file-iterator": "^2.0.1", + "phpunit/php-text-template": "^1.2.1", + "phpunit/php-timer": "^2.1", + "sebastian/comparator": "^3.0", + "sebastian/diff": "^3.0", + "sebastian/environment": "^4.0", + "sebastian/exporter": "^3.1", + "sebastian/global-state": "^2.0", + "sebastian/object-enumerator": "^3.0.3", + "sebastian/resource-operations": "^2.0", + "sebastian/version": "^2.0.1" }, "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2" + "phpunit/phpunit-mock-objects": "*" }, "require-dev": { "ext-pdo": "*" }, "suggest": { + "ext-soap": "*", "ext-xdebug": "*", - "phpunit/php-invoker": "~1.1" + "phpunit/php-invoker": "^2.0" }, "bin": [ "phpunit" @@ -611,7 +736,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.7.x-dev" + "dev-master": "7.5-dev" } }, "autoload": { @@ -637,86 +762,27 @@ "testing", "xunit" ], - "time": "2016-12-13 16:19:44" - }, - { - "name": "phpunit/phpunit-mock-objects", - "version": "3.4.3", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", - "reference": "3ab72b65b39b491e0c011e2e09bb2206c2aa8e24", - "shasum": "" - }, - "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.6 || ^7.0", - "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2 || ^2.0" - }, - "conflict": { - "phpunit/phpunit": "<5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.4" - }, - "suggest": { - "ext-soap": "*" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2.x-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", - "keywords": [ - "mock", - "xunit" - ], - "time": "2016-12-08 20:27:08" + "time": "2019-05-14T04:53:02+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "1.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe" + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/c36f5e7cfce482fde5bf8d10d41a53591e0198fe", - "reference": "c36f5e7cfce482fde5bf8d10d41a53591e0198fe", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", + "reference": "4419fcdb5eabb9caa61a27c7a1db532a6b55dd18", "shasum": "" }, "require": { - "php": ">=5.6" + "php": "^5.6 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~5" + "phpunit/phpunit": "^5.7 || ^6.0" }, "type": "library", "extra": { @@ -741,34 +807,34 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2016-02-13 06:45:14" + "time": "2017-03-04T06:30:41+00:00" }, { "name": "sebastian/comparator", - "version": "1.2.2", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f" + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/6a1ed12e8b2409076ab22e3897126211ff8b1f7f", - "reference": "6a1ed12e8b2409076ab22e3897126211ff8b1f7f", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" + "php": "^7.1", + "sebastian/diff": "^3.0", + "sebastian/exporter": "^3.1" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -799,38 +865,39 @@ } ], "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", + "homepage": "https://github.com/sebastianbergmann/comparator", "keywords": [ "comparator", "compare", "equality" ], - "time": "2016-11-19 09:18:40" + "time": "2018-07-12T15:12:46+00:00" }, { "name": "sebastian/diff", - "version": "1.4.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e" + "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/13edfd8706462032c2f52b4b862974dd46b71c9e", - "reference": "13edfd8706462032c2f52b4b862974dd46b71c9e", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/720fcc7e9b5cf384ea68d9d930d480907a0c1a29", + "reference": "720fcc7e9b5cf384ea68d9d930d480907a0c1a29", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "~4.8" + "phpunit/phpunit": "^7.5 || ^8.0", + "symfony/process": "^2 || ^3.3 || ^4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -855,34 +922,40 @@ "description": "Diff implementation", "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ - "diff" + "diff", + "udiff", + "unidiff", + "unified diff" ], - "time": "2015-12-08 07:14:41" + "time": "2019-02-04T06:01:07+00:00" }, { "name": "sebastian/environment", - "version": "2.0.0", + "version": "4.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" + "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/f2a2c8e1c97c11ace607a7a667d73d47c19fe404", + "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^5.0" + "phpunit/phpunit": "^7.5" + }, + "suggest": { + "ext-posix": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "4.2-dev" } }, "autoload": { @@ -907,34 +980,34 @@ "environment", "hhvm" ], - "time": "2016-11-26 07:53:53" + "time": "2019-05-05T09:05:15+00:00" }, { "name": "sebastian/exporter", - "version": "2.0.0", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4" + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", - "reference": "ce474bdd1a34744d7ac5d6aad3a46d48d9bac4c4", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/recursion-context": "~2.0" + "php": "^7.0", + "sebastian/recursion-context": "^3.0" }, "require-dev": { "ext-mbstring": "*", - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.1.x-dev" } }, "autoload": { @@ -974,27 +1047,27 @@ "export", "exporter" ], - "time": "2016-11-19 08:54:04" + "time": "2017-04-03T13:19:02+00:00" }, { "name": "sebastian/global-state", - "version": "1.1.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", - "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^6.0" }, "suggest": { "ext-uopz": "*" @@ -1002,7 +1075,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -1025,33 +1098,34 @@ "keywords": [ "global state" ], - "time": "2015-10-12 03:26:01" + "time": "2017-04-27T15:39:26+00:00" }, { "name": "sebastian/object-enumerator", - "version": "2.0.0", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35" + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", - "reference": "96f8a3f257b69e8128ad74d3a7fd464bcbaa3b35", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/7cfd9e65d11ffb5af41198476395774d4c8a84c5", + "reference": "7cfd9e65d11ffb5af41198476395774d4c8a84c5", "shasum": "" }, "require": { - "php": ">=5.6", - "sebastian/recursion-context": "~2.0" + "php": "^7.0", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" }, "require-dev": { - "phpunit/phpunit": "~5" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -1071,32 +1145,77 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2016-11-19 07:35:10" + "time": "2017-08-03T12:35:26+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "773f97c67f28de00d397be301821b06708fca0be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/773f97c67f28de00d397be301821b06708fca0be", + "reference": "773f97c67f28de00d397be301821b06708fca0be", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "time": "2017-03-29T09:07:27+00:00" }, { "name": "sebastian/recursion-context", - "version": "2.0.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a" + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/2c3ba150cbec723aa057506e73a8d33bdb286c9a", - "reference": "2c3ba150cbec723aa057506e73a8d33bdb286c9a", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "3.0.x-dev" } }, "autoload": { @@ -1124,29 +1243,29 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2016-11-19 07:33:16" + "time": "2017-03-03T06:23:57+00:00" }, { "name": "sebastian/resource-operations", - "version": "1.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52" + "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", - "reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9", + "reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9", "shasum": "" }, "require": { - "php": ">=5.6.0" + "php": "^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -1166,7 +1285,7 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2015-07-28 20:34:47" + "time": "2018-10-04T04:07:39+00:00" }, { "name": "sebastian/version", @@ -1209,43 +1328,40 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03 07:35:21" + "time": "2016-10-03T07:35:21+00:00" }, { - "name": "symfony/yaml", - "version": "v3.2.1", + "name": "symfony/polyfill-ctype", + "version": "v1.11.0", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "a7095af4b97a0955f85c8989106c249fa649011f" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "82ebae02209c21113908c229e9883c419720738a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/a7095af4b97a0955f85c8989106c249fa649011f", - "reference": "a7095af4b97a0955f85c8989106c249fa649011f", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", + "reference": "82ebae02209c21113908c229e9883c419720738a", "shasum": "" }, "require": { - "php": ">=5.5.9" - }, - "require-dev": { - "symfony/console": "~2.8|~3.0" + "php": ">=5.3.3" }, "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "ext-ctype": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-master": "1.11-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Yaml\\": "" + "Symfony\\Polyfill\\Ctype\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -1253,35 +1369,82 @@ "MIT" ], "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" } ], - "description": "Symfony Yaml Component", + "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", - "time": "2016-12-10 10:07:06" + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2019-02-06T07:57:58+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/1c42705be2b6c1de5904f8afacef5895cab44bf8", + "reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "time": "2019-04-04T09:56:43+00:00" }, { "name": "webmozart/assert", - "version": "1.2.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f" + "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f", - "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f", + "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", + "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": "^5.3.3 || ^7.0", + "symfony/polyfill-ctype": "^1.8" }, "require-dev": { "phpunit/phpunit": "^4.6", @@ -1314,7 +1477,7 @@ "check", "validate" ], - "time": "2016-11-23 20:04:58" + "time": "2018-12-25T11:19:39+00:00" } ], "aliases": [], @@ -1323,7 +1486,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.6.0" + "php": ">=7.1" }, "platform-dev": [] } diff --git a/tests/DecoderTest.php b/tests/DecoderTest.php index bd1cf97..bcd3558 100644 --- a/tests/DecoderTest.php +++ b/tests/DecoderTest.php @@ -1,12 +1,12 @@ Date: Thu, 23 May 2019 19:48:41 +0200 Subject: [PATCH 29/70] Test on 7.1 as well --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index ae99eb9..c19c02d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: php php: + - 7.1 - 7.2 - 7.3 From 513a3bf2c1a006ad2e7f6fe429247e9357bedf7f Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Fri, 24 May 2019 13:10:07 +0200 Subject: [PATCH 30/70] Add script for running tests with coverage --- composer.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/composer.json b/composer.json index 0a5259c..49bf0dd 100644 --- a/composer.json +++ b/composer.json @@ -45,6 +45,9 @@ "test:phpunit:coverage": "vendor/bin/phpunit --verbose --coverage-html build/coverage", "test": [ "@test:phpunit" + ], + "test:coverage": [ + "@test:phpunit:coverage" ] } } \ No newline at end of file From c2486afb3c942788ce391106619f1124f278ee26 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Fri, 24 May 2019 13:11:05 +0200 Subject: [PATCH 31/70] Use strict types Replace type checking for proper type hints --- src/Decoder.php | 54 +++++++--------------------------------- src/DecoderInterface.php | 16 ++++++------ src/Encoder.php | 54 ++++++++-------------------------------- src/EncoderInterface.php | 18 ++++++-------- src/Torrent.php | 6 ++--- tests/DecoderTest.php | 29 ++++++++++----------- tests/EncoderTest.php | 45 ++++++++------------------------- tests/TorrentTest.php | 2 +- 8 files changed, 62 insertions(+), 162 deletions(-) diff --git a/src/Decoder.php b/src/Decoder.php index 8ab49e9..5be3ab9 100644 --- a/src/Decoder.php +++ b/src/Decoder.php @@ -1,21 +1,11 @@ -encoder = $encoder; } - /** - * {@inheritdoc} - */ - public function decodeFile($file, $strict = false) { + public function decodeFile(string $file, bool $strict = false) : array { if (!is_readable($file)) { throw new InvalidArgumentException('File ' . $file . ' does not exist or can not be read.'); } @@ -45,10 +32,7 @@ public function decodeFile($file, $strict = false) { return $dictionary; } - /** - * {@inheritdoc} - */ - public function decode($string) { + public function decode(string $string) { if ($string[0] === 'i') { return $this->decodeInteger($string); } else if ($string[0] === 'l') { @@ -62,10 +46,7 @@ public function decode($string) { throw new InvalidArgumentException('Parameter is not correctly encoded.'); } - /** - * {@inheritdoc} - */ - public function decodeInteger($integer) { + public function decodeInteger(string $integer) : int { if ($integer[0] !== 'i' || (!$ePos = strpos($integer, 'e'))) { throw new InvalidArgumentException('Invalid integer. Integers must start wth "i" and end with "e".'); } @@ -77,29 +58,18 @@ public function decodeInteger($integer) { throw new InvalidArgumentException('Invalid integer value.'); } - if (PHP_INT_SIZE === 8) { - return (int) $integer; - } - - // Return integer as a string on 32-bit systems - // @codeCoverageIgnoreStart - return $integer; - // @codeCoverageIgnoreEnd + return (int) $integer; } - /** - * {@inheritdoc} - */ - public function decodeString($string) { + public function decodeString(string $string) : string { $stringParts = explode(':', $string, 2); - // The string must have two parts if (count($stringParts) !== 2) { throw new InvalidArgumentException('Invalid string. Strings consist of two parts separated by ":".'); } $length = (int) $stringParts[0]; - $lengthLen = strlen($length); + $lengthLen = strlen((string) $length); if (($lengthLen + 1 + $length) > strlen($string)) { throw new InvalidArgumentException('The length of the string does not match the prefix of the encoded data.'); @@ -108,10 +78,7 @@ public function decodeString($string) { return substr($string, ($lengthLen + 1), $length); } - /** - * {@inheritdoc} - */ - public function decodeList($list) { + public function decodeList(string $list) : array { if ($list[0] !== 'l') { throw new InvalidArgumentException('Parameter is not an encoded list.'); } @@ -135,10 +102,7 @@ public function decodeList($list) { return $ret; } - /** - * {@inheritdoc} - */ - public function decodeDictionary($dictionary) { + public function decodeDictionary(string $dictionary) : array { if ($dictionary[0] !== 'd') { throw new InvalidArgumentException('Parameter is not an encoded dictionary.'); } diff --git a/src/DecoderInterface.php b/src/DecoderInterface.php index 8c17ffc..4ebcfde 100644 --- a/src/DecoderInterface.php +++ b/src/DecoderInterface.php @@ -1,4 +1,4 @@ -params = array_replace($this->params, $params); } - /** - * {@inheritdoc} - */ - public function encode($var) { - if ($this->isInt($var)) { + public function encode($var) : string { + if (is_int($var)) { return $this->encodeInteger($var); } else if (is_string($var)) { return $this->encodeString($var); @@ -47,35 +44,18 @@ public function encode($var) { return $this->encodeList($var); } - throw new InvalidArgumentException('Variables of type ' . gettype($var) . ' can not be encoded.'); + throw new InvalidArgumentException(sprintf('Variables of type %s can not be encoded.', gettype($var))); } - /** - * {@inheritdoc} - */ - public function encodeInteger($integer) { - if ($this->isInt($integer)) { - return 'i' . $integer . 'e'; - } - - throw new InvalidArgumentException('Expected an integer.'); + public function encodeInteger(int $integer) : string { + return 'i' . $integer . 'e'; } - /** - * {@inheritdoc} - */ - public function encodeString($string) { - if (!is_string($string)) { - throw new InvalidArgumentException('Expected string, got: ' . gettype($string) . '.'); - } - - return strlen($string) . ':' . $string; + public function encodeString(string $string) : string { + return sprintf('%d:%s', strlen($string), $string); } - /** - * {@inheritdoc} - */ - public function encodeList(array $list) { + public function encodeList(array $list) : string { $ret = 'l'; foreach ($list as $value) { @@ -85,10 +65,7 @@ public function encodeList(array $list) { return $ret . 'e'; } - /** - * {@inheritdoc} - */ - public function encodeDictionary(array $dictionary) { + public function encodeDictionary(array $dictionary) : string { ksort($dictionary); $ret = 'd'; @@ -99,15 +76,4 @@ public function encodeDictionary(array $dictionary) { return $ret . 'e'; } - - /** - * Check if a variable is an integer - * - * @param int|string - * @return boolean - */ - private function isInt($var) { - return is_int($var) || - (PHP_INT_SIZE === 4 && is_numeric($var) && (strpos($var, '.') === false)); - } } diff --git a/src/EncoderInterface.php b/src/EncoderInterface.php index c2aa588..9905604 100644 --- a/src/EncoderInterface.php +++ b/src/EncoderInterface.php @@ -1,4 +1,4 @@ - basename($absolutePath), 'filesize' => filesize($absolutePath), ]; - } else if (is_dir($absolutePath)) { + } else if (false !== $absolutePath && is_dir($absolutePath)) { $dir = new RecursiveDirectoryIterator($absolutePath); $iterator = new RecursiveIteratorIterator($dir); diff --git a/tests/DecoderTest.php b/tests/DecoderTest.php index bcd3558..8864abe 100644 --- a/tests/DecoderTest.php +++ b/tests/DecoderTest.php @@ -1,4 +1,4 @@ -assertEquals($value, $this->decoder->decodeInteger($encoded)); } @@ -47,7 +44,7 @@ public function testDecoderInteger($encoded, $value) { * * @return array[] */ - public function getDecodeInvalidIntegerData() { + public function getDecodeInvalidIntegerData() : array { return [ ['i01e'], ['i-01e'], @@ -62,7 +59,7 @@ public function getDecodeInvalidIntegerData() { * @expectedExceptionMessage Invalid integer value. * @param string $value */ - public function testDecodeInvalidInteger($value) { + public function testDecodeInvalidInteger(string $value) { $this->decoder->decodeInteger($value); } @@ -89,7 +86,7 @@ public function testDecodePartialInteger() { * * @return array[] */ - public function getDecodeStringData() { + public function getDecodeStringData() : array { return [ ['4:spam', 'spam'], ['11:test string', 'test string'], @@ -103,7 +100,7 @@ public function getDecodeStringData() { * @param string $encoded * @param string $value */ - public function testDecodeString($encoded, $value) { + public function testDecodeString(string $encoded, string $value) { $this->assertSame($value, $this->decoder->decodeString($encoded)); } @@ -130,7 +127,7 @@ public function testDecodeStringWithInvalidLength() { * * @return array[] */ - public function getDecodeListData() { + public function getDecodeListData() : array { return [ ['li1ei2ei3ee', [1, 2, 3]], ]; @@ -142,7 +139,7 @@ public function getDecodeListData() { * @param string $encoded * @param array $value */ - public function testDecodeList($encoded, array $value) { + public function testDecodeList(string $encoded, array $value) { $this->assertEquals($value, $this->decoder->decodeList($encoded)); } @@ -160,7 +157,7 @@ public function testDecodeInvalidList() { * * @return array[] */ - public function getDecodeDictionaryData() { + public function getDecodeDictionaryData() : array { return [ ['d3:foo3:bar4:spam4:eggse', ['foo' => 'bar', 'spam' => 'eggs']], ]; @@ -172,7 +169,7 @@ public function getDecodeDictionaryData() { * @param string $encoded * @param array $value */ - public function testDecodeDictionary($encoded, array $value) { + public function testDecodeDictionary(string $encoded, array $value) { $this->assertSame($value, $this->decoder->decodeDictionary($encoded)); } @@ -190,7 +187,7 @@ public function testDecodeInvalidDictionary() { * * @return array[] */ - public function getGenericDecodeData() { + public function getGenericDecodeData() : array { return [ ['i1e', 1], ['4:spam', 'spam'], @@ -206,7 +203,7 @@ public function getGenericDecodeData() { * @param string $encoded * @param int|string|array $value */ - public function testGenericDecode($encoded, $value) { + public function testGenericDecode(string $encoded, $value) { $this->assertEquals($value, $this->decoder->decode($encoded)); } diff --git a/tests/EncoderTest.php b/tests/EncoderTest.php index 0e0ddc1..db7ccfa 100644 --- a/tests/EncoderTest.php +++ b/tests/EncoderTest.php @@ -1,4 +1,4 @@ -assertSame($encoded, $this->encoder->encodeInteger($value)); } - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Expected an integer. - * @covers ::encodeInteger - */ - public function testEncodeNonIntegerAsInteger() { - $this->encoder->encodeInteger('one'); - } - /** * Data provider * * @return array[] */ - public function getEncodeStringData() { + public function getEncodeStringData() : array { return [ ['spam', '4:spam'], ['foobar', '6:foobar'], @@ -72,25 +59,16 @@ public function getEncodeStringData() { * @param string $value * @param string $encoded */ - public function testEncodeString($value, $encoded) { + public function testEncodeString(string $value, string $encoded) { $this->assertSame($encoded, $this->encoder->encodeString($value)); } - /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Expected string, got: integer. - * @covers ::encodeString - */ - public function testEncodeNonStringAsString() { - $this->encoder->encodeString(1); - } - /** * Data provider * * @return array[] */ - public function getEncodeListData() { + public function getEncodeListData() : array { return [ [['spam', 1, [1]], 'l4:spami1eli1eee'], ]; @@ -102,7 +80,7 @@ public function getEncodeListData() { * @param array $value * @param string $encoded */ - public function testEncodeList(array $value, $encoded) { + public function testEncodeList(array $value, string $encoded) { $this->assertSame($encoded, $this->encoder->encodeList($value)); } @@ -111,7 +89,7 @@ public function testEncodeList(array $value, $encoded) { * * @return array[] */ - public function getEncodeDictionaryData() { + public function getEncodeDictionaryData() : array { return [ [['1' => 'foo', 'foo' => 'bar', 'list' => [1, 2, 3]], 'd3:foo3:bar4:listli1ei2ei3ee1:13:fooe'], [['foo' => 'bar', 'spam' => 'eggs'], 'd3:foo3:bar4:spam4:eggse'], @@ -125,7 +103,7 @@ public function getEncodeDictionaryData() { * @param array $value * @param string $encoded */ - public function testEncodeDictionary(array $value, $encoded) { + public function testEncodeDictionary(array $value, string $encoded) { $this->assertSame($encoded, $this->encoder->encodeDictionary($value)); } @@ -134,7 +112,7 @@ public function testEncodeDictionary(array $value, $encoded) { * * @return array[] */ - public function getEncodeData() { + public function getEncodeData() : array { return [ [1, 'i1e'], ['spam', '4:spam'], @@ -146,11 +124,10 @@ public function getEncodeData() { /** * @dataProvider getEncodeData * @covers ::encode - * @covers ::isInt * @param string|int|array $value * @param string $encoded */ - public function testEncodeUsingGenericMethod($value, $encoded) { + public function testEncodeUsingGenericMethod($value, string $encoded) { $this->assertSame($encoded, $this->encoder->encode($value)); } diff --git a/tests/TorrentTest.php b/tests/TorrentTest.php index 241f899..6b8cfcb 100644 --- a/tests/TorrentTest.php +++ b/tests/TorrentTest.php @@ -1,4 +1,4 @@ - Date: Fri, 24 May 2019 13:43:53 +0200 Subject: [PATCH 32/70] Add QA tools and update scripts --- .travis.yml | 6 +- composer.json | 36 +- composer.lock | 1270 ++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 1295 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index c19c02d..f3e54af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,9 +6,7 @@ php: - 7.3 before_script: - - composer self-update - - composer install --prefer-source + - composer install -n --prefer-dist script: - - composer lint - - composer test + - composer ci diff --git a/composer.json b/composer.json index 49bf0dd..d9f85e6 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { - "name": "christeredvartsen/php-bittorrent", + "name": "christeredvartsen/bittorrent", "type": "library", - "description": "PHP BitTorrent is a set of components that can be used to interact with torrent files (read+write) and classes that can encode/decode to/from the BitTorrent format.", + "description": "A set of components that can be used to interact with torrent files (read+write) and classes that can encode/decode to/from the BitTorrent format.", "keywords": [ "bittorrent", "torrent" @@ -18,7 +18,9 @@ "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^7.0", + "phploc/phploc": "^4.0", + "phpstan/phpstan": "^0.11.7" }, "support": { "source": "https://github.com/christeredvartsen/php-bittorrent", @@ -35,19 +37,31 @@ } }, "scripts": { - "lint": "for file in `git ls-files '*php'`; do php -l $file; done", - "prepare": [ - "rm -rf build", - "mkdir build", - "mkdir build/coverage" + "clean:build": "rm -rf build", + "qa:lint": "for file in `git ls-files '*php'`; do php -l $file; done", + "qa:phpstan": "vendor/bin/phpstan analyse src tests", + "qa:phploc": [ + "rm -rf build/artifacts/phploc", + "mkdir -p build/artifacts/phploc", + "vendor/bin/phploc --log-xml build/artifacts/phploc/phploc.xml src" + ], + "qa": [ + "@qa:lint", + "@qa:phploc", + "@qa:phpstan" ], "test:phpunit": "vendor/bin/phpunit --verbose", - "test:phpunit:coverage": "vendor/bin/phpunit --verbose --coverage-html build/coverage", + "test:phpunit:coverage": [ + "rm -rf build/artifacts/phpunit/coverage", + "mkdir -p build/artifacts/phpunit/coverage", + "vendor/bin/phpunit --verbose --coverage-html build/artifacts/phpunit/coverage" + ], "test": [ "@test:phpunit" ], - "test:coverage": [ - "@test:phpunit:coverage" + "ci": [ + "@qa", + "@test" ] } } \ No newline at end of file diff --git a/composer.lock b/composer.lock index 8a6a641..e612640 100644 --- a/composer.lock +++ b/composer.lock @@ -4,9 +4,53 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "a8fc0535bffbadc20d4b5becafb86b14", + "content-hash": "ddacbc9e11aef638f33c440a178bb091", "packages": [], "packages-dev": [ + { + "name": "composer/xdebug-handler", + "version": "1.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "d17708133b6c276d6e42ef887a877866b909d892" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/d17708133b6c276d6e42ef887a877866b909d892", + "reference": "d17708133b6c276d6e42ef887a877866b909d892", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0", + "psr/log": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "time": "2019-01-28T20:25:53+00:00" + }, { "name": "doctrine/instantiator", "version": "1.2.0", @@ -63,6 +107,57 @@ ], "time": "2019-03-17T17:37:11+00:00" }, + { + "name": "jean85/pretty-package-versions", + "version": "1.2", + "source": { + "type": "git", + "url": "https://github.com/Jean85/pretty-package-versions.git", + "reference": "75c7effcf3f77501d0e0caa75111aff4daa0dd48" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/75c7effcf3f77501d0e0caa75111aff4daa0dd48", + "reference": "75c7effcf3f77501d0e0caa75111aff4daa0dd48", + "shasum": "" + }, + "require": { + "ocramius/package-versions": "^1.2.0", + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Jean85\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alessandro Lai", + "email": "alessandro.lai85@gmail.com" + } + ], + "description": "A wrapper for ocramius/package-versions to get pretty versions strings", + "keywords": [ + "composer", + "package", + "release", + "versions" + ], + "time": "2018-06-13T13:22:40+00:00" + }, { "name": "myclabs/deep-copy", "version": "1.9.1", @@ -111,6 +206,630 @@ ], "time": "2019-04-07T13:18:21+00:00" }, + { + "name": "nette/bootstrap", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/nette/bootstrap.git", + "reference": "e1075af05c211915e03e0c86542f3ba5433df4a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/bootstrap/zipball/e1075af05c211915e03e0c86542f3ba5433df4a3", + "reference": "e1075af05c211915e03e0c86542f3ba5433df4a3", + "shasum": "" + }, + "require": { + "nette/di": "^3.0", + "nette/utils": "^3.0", + "php": ">=7.1" + }, + "require-dev": { + "latte/latte": "^2.2", + "nette/application": "^3.0", + "nette/caching": "^3.0", + "nette/database": "^3.0", + "nette/forms": "^3.0", + "nette/http": "^3.0", + "nette/mail": "^3.0", + "nette/robot-loader": "^3.0", + "nette/safe-stream": "^2.2", + "nette/security": "^3.0", + "nette/tester": "^2.0", + "tracy/tracy": "^2.6" + }, + "suggest": { + "nette/robot-loader": "to use Configurator::createRobotLoader()", + "tracy/tracy": "to use Configurator::enableTracy()" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🅱 Nette Bootstrap: the simple way to configure and bootstrap your Nette application.", + "homepage": "https://nette.org", + "keywords": [ + "bootstrapping", + "configurator", + "nette" + ], + "time": "2019-03-26T12:59:07+00:00" + }, + { + "name": "nette/di", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/nette/di.git", + "reference": "19d83539245aaacb59470828919182411061841f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/di/zipball/19d83539245aaacb59470828919182411061841f", + "reference": "19d83539245aaacb59470828919182411061841f", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "nette/neon": "^3.0", + "nette/php-generator": "^3.2.2", + "nette/robot-loader": "^3.2", + "nette/schema": "^1.0", + "nette/utils": "^3.0", + "php": ">=7.1" + }, + "conflict": { + "nette/bootstrap": "<3.0" + }, + "require-dev": { + "nette/tester": "^2.2", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ], + "files": [ + "src/compatibility.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "💎 Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP 7.1 features.", + "homepage": "https://nette.org", + "keywords": [ + "compiled", + "di", + "dic", + "factory", + "ioc", + "nette", + "static" + ], + "time": "2019-04-03T19:35:46+00:00" + }, + { + "name": "nette/finder", + "version": "v2.5.0", + "source": { + "type": "git", + "url": "https://github.com/nette/finder.git", + "reference": "6be1b83ea68ac558aff189d640abe242e0306fe2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/finder/zipball/6be1b83ea68ac558aff189d640abe242e0306fe2", + "reference": "6be1b83ea68ac558aff189d640abe242e0306fe2", + "shasum": "" + }, + "require": { + "nette/utils": "^2.4 || ~3.0.0", + "php": ">=7.1" + }, + "conflict": { + "nette/nette": "<2.2" + }, + "require-dev": { + "nette/tester": "^2.0", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "? Nette Finder: find files and directories with an intuitive API.", + "homepage": "https://nette.org", + "keywords": [ + "filesystem", + "glob", + "iterator", + "nette" + ], + "time": "2019-02-28T18:13:25+00:00" + }, + { + "name": "nette/neon", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/nette/neon.git", + "reference": "cbff32059cbdd8720deccf9e9eace6ee516f02eb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/neon/zipball/cbff32059cbdd8720deccf9e9eace6ee516f02eb", + "reference": "cbff32059cbdd8720deccf9e9eace6ee516f02eb", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "ext-json": "*", + "php": ">=7.0" + }, + "require-dev": { + "nette/tester": "^2.0", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "? Nette NEON: encodes and decodes NEON file format.", + "homepage": "http://ne-on.org", + "keywords": [ + "export", + "import", + "neon", + "nette", + "yaml" + ], + "time": "2019-02-05T21:30:40+00:00" + }, + { + "name": "nette/php-generator", + "version": "v3.2.2", + "source": { + "type": "git", + "url": "https://github.com/nette/php-generator.git", + "reference": "acff8b136fad84b860a626d133e791f95781f9f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/php-generator/zipball/acff8b136fad84b860a626d133e791f95781f9f5", + "reference": "acff8b136fad84b860a626d133e791f95781f9f5", + "shasum": "" + }, + "require": { + "nette/utils": "^2.4.2 || ~3.0.0", + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "^2.0", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 7.3 features.", + "homepage": "https://nette.org", + "keywords": [ + "code", + "nette", + "php", + "scaffolding" + ], + "time": "2019-03-15T03:41:13+00:00" + }, + { + "name": "nette/robot-loader", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/nette/robot-loader.git", + "reference": "0712a0e39ae7956d6a94c0ab6ad41aa842544b5c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/robot-loader/zipball/0712a0e39ae7956d6a94c0ab6ad41aa842544b5c", + "reference": "0712a0e39ae7956d6a94c0ab6ad41aa842544b5c", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "nette/finder": "^2.5", + "nette/utils": "^3.0", + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "^2.0", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "? Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.", + "homepage": "https://nette.org", + "keywords": [ + "autoload", + "class", + "interface", + "nette", + "trait" + ], + "time": "2019-03-08T21:57:24+00:00" + }, + { + "name": "nette/schema", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/nette/schema.git", + "reference": "6241d8d4da39e825dd6cb5bfbe4242912f4d7e4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/schema/zipball/6241d8d4da39e825dd6cb5bfbe4242912f4d7e4d", + "reference": "6241d8d4da39e825dd6cb5bfbe4242912f4d7e4d", + "shasum": "" + }, + "require": { + "nette/utils": "^3.0.1", + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "^2.2", + "tracy/tracy": "^2.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", + "keywords": [ + "config", + "nette" + ], + "time": "2019-04-03T15:53:25+00:00" + }, + { + "name": "nette/utils", + "version": "v3.0.1", + "source": { + "type": "git", + "url": "https://github.com/nette/utils.git", + "reference": "bd961f49b211997202bda1d0fbc410905be370d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/utils/zipball/bd961f49b211997202bda1d0fbc410905be370d4", + "reference": "bd961f49b211997202bda1d0fbc410905be370d4", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "nette/tester": "~2.0", + "tracy/tracy": "^2.3" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize() and toAscii()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-xml": "to use Strings::length() etc. when mbstring is not available" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0", + "GPL-3.0" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "time": "2019-03-22T01:00:30+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.2.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "5221f49a608808c1e4d436df32884cbc1b821ac0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/5221f49a608808c1e4d436df32884cbc1b821ac0", + "reference": "5221f49a608808c1e4d436df32884cbc1b821ac0", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.5 || ^7.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "time": "2019-02-16T20:54:15+00:00" + }, + { + "name": "ocramius/package-versions", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/Ocramius/PackageVersions.git", + "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", + "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0.0", + "php": "^7.1.0" + }, + "require-dev": { + "composer/composer": "^1.6.3", + "doctrine/coding-standard": "^5.0.1", + "ext-zip": "*", + "infection/infection": "^0.7.1", + "phpunit/phpunit": "^7.0.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PackageVersions\\Installer", + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "PackageVersions\\": "src/PackageVersions" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", + "time": "2019-02-21T12:16:21+00:00" + }, { "name": "phar-io/manifest", "version": "1.0.3", @@ -365,6 +1084,55 @@ ], "time": "2017-07-14T14:27:02+00:00" }, + { + "name": "phploc/phploc", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phploc.git", + "reference": "6a8a9416517b82d6326ac9c2d040ad53c13654eb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phploc/zipball/6a8a9416517b82d6326ac9c2d040ad53c13654eb", + "reference": "6a8a9416517b82d6326ac9c2d040ad53c13654eb", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "sebastian/finder-facade": "^1.1", + "sebastian/version": "^2.0", + "symfony/console": "^2.7|^3.0|^4.0" + }, + "bin": [ + "phploc" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "A tool for quickly measuring the size of a PHP project.", + "homepage": "https://github.com/sebastianbergmann/phploc", + "time": "2017-11-18T17:35:43+00:00" + }, { "name": "phpspec/prophecy", "version": "1.8.0", @@ -426,7 +1194,128 @@ "spy", "stub" ], - "time": "2018-08-05T17:53:17+00:00" + "time": "2018-08-05T17:53:17+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "0.3.3", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "472d3161d289f652713a5e353532fa4592663a57" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/472d3161d289f652713a5e353532fa4592663a57", + "reference": "472d3161d289f652713a5e353532fa4592663a57", + "shasum": "" + }, + "require": { + "php": "~7.1" + }, + "require-dev": { + "consistence/coding-standard": "^3.5", + "jakub-onderka/php-parallel-lint": "^0.9.2", + "phing/phing": "^2.16.0", + "phpstan/phpstan": "^0.10", + "phpunit/phpunit": "^6.3", + "slevomat/coding-standard": "^4.7.2", + "squizlabs/php_codesniffer": "^3.3.2", + "symfony/process": "^3.4 || ^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.3-dev" + } + }, + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "time": "2019-04-23T20:26:19+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "0.11.7", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "32d87d746c70785f78d239855782d27cde0eb6ee" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/32d87d746c70785f78d239855782d27cde0eb6ee", + "reference": "32d87d746c70785f78d239855782d27cde0eb6ee", + "shasum": "" + }, + "require": { + "composer/xdebug-handler": "^1.3.0", + "jean85/pretty-package-versions": "^1.0.3", + "nette/bootstrap": "^2.4 || ^3.0", + "nette/di": "^2.4.7 || ^3.0", + "nette/robot-loader": "^3.0.1", + "nette/schema": "^1.0", + "nette/utils": "^2.4.5 || ^3.0", + "nikic/php-parser": "^4.0.2", + "php": "~7.1", + "phpstan/phpdoc-parser": "^0.3", + "symfony/console": "~3.2 || ~4.0", + "symfony/finder": "~3.2 || ~4.0" + }, + "conflict": { + "symfony/console": "3.4.16 || 4.1.5" + }, + "require-dev": { + "brianium/paratest": "^2.0", + "consistence/coding-standard": "^3.5", + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4", + "ext-intl": "*", + "ext-mysqli": "*", + "ext-soap": "*", + "ext-zip": "*", + "jakub-onderka/php-parallel-lint": "^1.0", + "localheinz/composer-normalize": "^1.1.0", + "phing/phing": "^2.16.0", + "phpstan/phpstan-deprecation-rules": "^0.11", + "phpstan/phpstan-php-parser": "^0.11", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-strict-rules": "^0.11", + "phpunit/phpunit": "^7.0", + "slevomat/coding-standard": "^4.7.2", + "squizlabs/php_codesniffer": "^3.3.2" + }, + "bin": [ + "bin/phpstan" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.11-dev" + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": [ + "src/", + "build/PHPStan" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "time": "2019-05-19T17:36:42+00:00" }, { "name": "phpunit/php-code-coverage", @@ -764,6 +1653,53 @@ ], "time": "2019-05-14T04:53:02+00:00" }, + { + "name": "psr/log", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2018-11-20T15:27:04+00:00" + }, { "name": "sebastian/code-unit-reverse-lookup", "version": "1.0.1", @@ -1049,6 +1985,45 @@ ], "time": "2017-04-03T13:19:02+00:00" }, + { + "name": "sebastian/finder-facade", + "version": "1.2.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/finder-facade.git", + "reference": "4a3174709c2dc565fe5fb26fcf827f6a1fc7b09f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/finder-facade/zipball/4a3174709c2dc565fe5fb26fcf827f6a1fc7b09f", + "reference": "4a3174709c2dc565fe5fb26fcf827f6a1fc7b09f", + "shasum": "" + }, + "require": { + "symfony/finder": "~2.3|~3.0|~4.0", + "theseer/fdomdocument": "~1.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FinderFacade is a convenience wrapper for Symfony's Finder component.", + "homepage": "https://github.com/sebastianbergmann/finder-facade", + "time": "2017-11-18T17:31:49+00:00" + }, { "name": "sebastian/global-state", "version": "2.0.0", @@ -1330,6 +2305,198 @@ "homepage": "https://github.com/sebastianbergmann/version", "time": "2016-10-03T07:35:21+00:00" }, + { + "name": "symfony/console", + "version": "v4.2.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "e2840bb38bddad7a0feaf85931e38fdcffdb2f81" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/e2840bb38bddad7a0feaf85931e38fdcffdb2f81", + "reference": "e2840bb38bddad7a0feaf85931e38fdcffdb2f81", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/contracts": "^1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2019-04-08T14:23:48+00:00" + }, + { + "name": "symfony/contracts", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/contracts.git", + "reference": "d3636025e8253c6144358ec0a62773cae588395b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/contracts/zipball/d3636025e8253c6144358ec0a62773cae588395b", + "reference": "d3636025e8253c6144358ec0a62773cae588395b", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "psr/cache": "^1.0", + "psr/container": "^1.0", + "symfony/polyfill-intl-idn": "^1.10" + }, + "suggest": { + "psr/cache": "When using the Cache contracts", + "psr/container": "When using the Service contracts", + "symfony/cache-contracts-implementation": "", + "symfony/event-dispatcher-implementation": "", + "symfony/http-client-contracts-implementation": "", + "symfony/service-contracts-implementation": "", + "symfony/translation-contracts-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\": "" + }, + "exclude-from-classmap": [ + "**/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A set of abstractions extracted out of the Symfony components", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-04-27T14:29:50+00:00" + }, + { + "name": "symfony/finder", + "version": "v4.2.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "e45135658bd6c14b61850bf131c4f09a55133f69" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/e45135658bd6c14b61850bf131c4f09a55133f69", + "reference": "e45135658bd6c14b61850bf131c4f09a55133f69", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2019-04-06T13:51:08+00:00" + }, { "name": "symfony/polyfill-ctype", "version": "v1.11.0", @@ -1388,6 +2555,105 @@ ], "time": "2019-02-06T07:57:58+00:00" }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.11.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", + "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.11-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2019-02-06T07:57:58+00:00" + }, + { + "name": "theseer/fdomdocument", + "version": "1.6.6", + "source": { + "type": "git", + "url": "https://github.com/theseer/fDOMDocument.git", + "reference": "6e8203e40a32a9c770bcb62fe37e68b948da6dca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/6e8203e40a32a9c770bcb62fe37e68b948da6dca", + "reference": "6e8203e40a32a9c770bcb62fe37e68b948da6dca", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "lib-libxml": "*", + "php": ">=5.3.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "lead" + } + ], + "description": "The classes contained within this repository extend the standard DOM to use exceptions at all occasions of errors instead of PHP warnings or notices. They also add various custom methods and shortcuts for convenience and to simplify the usage of DOM.", + "homepage": "https://github.com/theseer/fDOMDocument", + "time": "2017-06-30T11:53:12+00:00" + }, { "name": "theseer/tokenizer", "version": "1.1.2", From 48d04ff421ea439e6558592ef777db3dcf69db31 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Fri, 24 May 2019 13:44:45 +0200 Subject: [PATCH 33/70] Remove support for 32 bit --- src/Torrent.php | 17 +---------------- tests/TorrentTest.php | 6 ------ 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/src/Torrent.php b/src/Torrent.php index 5b86aae..33b9d19 100644 --- a/src/Torrent.php +++ b/src/Torrent.php @@ -577,7 +577,7 @@ public function getSize() { $size = 0; foreach ($files as $file) { - $size = $this->add($size, $file['length']); + $size += $file['length']; } return $size; @@ -646,19 +646,4 @@ public function isPrivate() { return (isset($info['private']) && $info['private'] === 1) ? true : false; } - - /** - * Add method that should work on both 32 and 64-bit platforms - * - * @param int $a - * @param int $b - * @return int|string - */ - private function add($a, $b) { - if (PHP_INT_SIZE === 4) { - return bcadd($a, $b); - } - - return $a + $b; - } } diff --git a/tests/TorrentTest.php b/tests/TorrentTest.php index 6b8cfcb..010c736 100644 --- a/tests/TorrentTest.php +++ b/tests/TorrentTest.php @@ -175,7 +175,6 @@ public function testGetFileList() { /** * @covers ::setInfo * @covers ::getSize - * @covers ::add */ public function testGetSizeWhenInfoBlockHasSeveralFiles() { $files = array( @@ -195,7 +194,6 @@ public function testGetSizeWhenInfoBlockHasSeveralFiles() { * @covers ::getCreatedBy * @covers ::getCreatedAt * @covers ::getSize - * @covers ::add * @covers ::getFileList */ public function testCreateFromTorrentFile() { @@ -255,7 +253,6 @@ public function testCreateFromTorrentFileWithExtra() { * @covers ::getAnnounce * @covers ::getName * @covers ::getSize - * @covers ::add * @covers ::getFileList */ public function testCreateFromPathWhenUsingADirectoryAsArgument() { @@ -274,7 +271,6 @@ public function testCreateFromPathWhenUsingADirectoryAsArgument() { * @covers ::getAnnounce * @covers ::getName * @covers ::getSize - * @covers ::add * @covers ::getFileList */ public function testCreateFromPathWhenUsingAFileAsArgument() { @@ -300,7 +296,6 @@ public function testCreateFromPathWhenUsingAFileAsArgument() { * @covers ::getCreatedBy * @covers ::getName * @covers ::getSize - * @covers ::add * @covers ::getFileList * @covers ::getAnnounceList * @covers ::getInfoPart @@ -497,7 +492,6 @@ public function testGetEncodedHash() { /** * @covers ::getSize - * @covers ::add */ public function testGetSizeWithLargeValues() { $torrent1 = Torrent::createFromTorrentFile(__DIR__ . '/_files/large_files.torrent'); From be241033b8464fb25ecbf9d3f9000e590d137a5e Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Fri, 24 May 2019 13:46:23 +0200 Subject: [PATCH 34/70] Update ChangeLog and README --- ChangeLog.md | 51 ++++++++++++++++++++++++ README.md | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100644 ChangeLog.md create mode 100644 README.md diff --git a/ChangeLog.md b/ChangeLog.md new file mode 100644 index 0000000..714f2de --- /dev/null +++ b/ChangeLog.md @@ -0,0 +1,51 @@ +Changelog for PHP BitTorrent +============================ + +Version 2.0.0 +------------- +__N/A__ + +* Use strict types +* Remove support for 32 bit platforms +* Bump PHP requirement from 5.3 to 7.1 +* Change namespace from PHP\BitTorrent to BitTorrent +* Renamed package from `christeredvartsen/php-bittorrent` to `christeredvartsen/bittorrent` +* Added method to check if the torrent is private (@stormwalkerec) + +Version 1.1.0 +------------- +__2013-01-11__ + +* Added parameters for the Encoder. The only parameter currently used it "encodeEmptyArrayAsDictionary" which will cause the encoder to encode empty arrays as "de" (empty dictionary) instead of "le" (empty list). + +Version 1.0.0 +------------- +__2013-01-05__ + +* Introduced a getEncodedHash method in the Torrent component to get the URL-encoded hash (Daniel Espendiller) +* Fix issue with integer overflow on 32-bit platforms +* Added method to get the hash of the torrent file (Daniel Espendiller) +* Dictionaries are now sorted by keys before they are encoded (as specified in in http://bittorrent.org/beps/bep\_0003.html) + +Version 0.3.0 +------------- +__2012-12-08__ + +* Fixed parse error in composer.json (Daniel Espendiller) +* Added interfaces for the encoder and the decoder (Matt Drollette) +* Fixed autoloader issues in composer.json (Matt Drollette) +* Library is from now on available as a PHAR archive as well +* Allow getting/setting extra fields from the torrent meta data (Matt Drollette) + +Version 0.2.0 +------------- +__2012-01-04__ + +* Use proper namespaces +* Changed API to use instance methods instead of static methods + +Version 0.0.1 +------------- +__2011-01-29__ + +* Initial release diff --git a/README.md b/README.md new file mode 100644 index 0000000..f55a843 --- /dev/null +++ b/README.md @@ -0,0 +1,107 @@ +# PHP BitTorrent +**PHP BitTorrent** is a set of components that can be used to interact with torrent files (read+write) and encode/decode to/from the BitTorrent format. + +[![Current Build Status](https://secure.travis-ci.org/christeredvartsen/php-bittorrent.png)](http://travis-ci.org/christeredvartsen/php-bittorrent) + +## Requirements +PHP BitTorrent requires PHP 7.1 or above. + +## Installation +PHP BitTorrent can be installed using [Composer](https://getcomposer.org): + +```json +{ + "require": { + "christeredvartsen/bittorrent": "^2.0" + } +} +``` + +## Using the PHP BitTorrent API +### Encode PHP variables + +```php +encodeString('Some string')); // string(14) "11:Some string" +var_dump($encoder->encodeInteger(42)); // int(42) +var_dump($encoder->encodeList([1, 2, 3]); // string(11) "li1ei2ei3ee" +var_dump($encoder->encodeDictionary(['foo' => 'bar', 'bar' => 'foo']); // string(22) "d3:foo3:bar3:bar3:fooe" +``` + +There is also a convenience method simply called `encode` in the `BitTorrent\Encoder` class that can be used to encode all encodable variables (integers, strings and arrays). + +### Decode BitTorrent encoded data + +```php +decodeString('11:Some string')); // string(11) "Some string" +var_dump($decoder->decodeInteger('i42e')); // int(42) +var_dump($decoder->decodeList('li1ei2ei3ee'); // array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) } +var_dump($decoder->decodeDictionary('d3:foo3:bar3:bar3:fooe'); // array(2) { ["foo"]=> string(3) "bar" ["bar"]=> string(3) "foo" } +``` + +There is also a convenience method called `decode` that can decode any BitTorrent encoded data. + +### Decode torrent files + +The decoder class also has a method for decoding a torrent file (which is an encoded dictionary): + +```php +decodeFile('/path/to/file.torrent'); +``` + +### Create new torrent files and open existing ones + +The `BitTorrent\Torrent` class represents a torrent file and can be used to create torrent files. + +```php +setComment('Some comment') + ->save('/save/to/path/file.torrent'); +``` + +The class can also load a torrent file: + +```php +setAnnounce('http://tracker/announce.php') // Override announce in original file + ->setComment('Some comment') // Override commend in original file + ->save('/save/to/path/file.torrent'); // Save to a new file +``` + +## License +Licensed under the MIT License. + +See [LICENSE](LICENSE) file. From 2818a49b6888538d74ae7de8bd1ce90092d0bb93 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Fri, 24 May 2019 13:57:37 +0200 Subject: [PATCH 35/70] Use arrow shorthand, and fix failing test --- tests/TorrentTest.php | 71 +++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/tests/TorrentTest.php b/tests/TorrentTest.php index 010c736..f4f576e 100644 --- a/tests/TorrentTest.php +++ b/tests/TorrentTest.php @@ -65,7 +65,7 @@ public function testSetGetCreationDate() { * @covers ::getInfo */ public function testSetGetInfo() { - $info = array('some' => 'data'); + $info = ['some' => 'data']; $this->assertSame($this->torrent, $this->torrent->setInfo($info)); $this->assertSame($info, $this->torrent->getInfo()); } @@ -85,7 +85,7 @@ public function testSetGetAnnounce() { * @covers ::getAnnounceList */ public function testSetGetAnnounceList() { - $announceList = array('http://tracker1/', 'http://tracker2/'); + $announceList = ['http://tracker1/', 'http://tracker2/']; $this->assertSame($this->torrent, $this->torrent->setAnnounceList($announceList)); $this->assertSame($announceList, $this->torrent->getAnnounceList()); } @@ -130,7 +130,7 @@ public function testGetFileListWithNoInfoBlockAdded() { */ public function testGetName() { $name = 'Some name'; - $info = array('name' => $name); + $info = ['name' => $name]; $this->torrent->setInfo($info); $this->assertSame($name, $this->torrent->getName()); } @@ -141,7 +141,7 @@ public function testGetName() { */ public function testGetSizeWhenLengthIsPresentInTheInfoBlock() { $length = 123; - $info = array('length' => $length); + $info = ['length' => $length]; $this->torrent->setInfo($info); $this->assertSame($length, $this->torrent->getSize()); } @@ -152,7 +152,7 @@ public function testGetSizeWhenLengthIsPresentInTheInfoBlock() { */ public function testGetFileListWhenInfoBlockOnlyContainsOneFile() { $name = 'some_filename'; - $info = array('length' => 123, 'name' => $name); + $info = ['length' => 123, 'name' => $name]; $this->torrent->setInfo($info); $this->assertSame($name, $this->torrent->getFileList()); } @@ -162,12 +162,12 @@ public function testGetFileListWhenInfoBlockOnlyContainsOneFile() { * @covers ::getFileList */ public function testGetFileList() { - $files = array( - array('length' => 12, 'path' => array('path', 'file.php')), - array('length' => 32, 'path' => array('path2', 'file2.php')), - array('length' => 123, 'path' => array('file.php')), - ); - $info = array('files' => $files); + $files = [ + ['length' => 12, 'path' => ['path', 'file.php']], + ['length' => 32, 'path' => ['path2', 'file2.php']], + ['length' => 123, 'path' => ['file.php']], + ]; + $info = ['files' => $files]; $this->torrent->setInfo($info); $this->assertSame($files, $this->torrent->getFileList()); } @@ -177,12 +177,12 @@ public function testGetFileList() { * @covers ::getSize */ public function testGetSizeWhenInfoBlockHasSeveralFiles() { - $files = array( - array('length' => 12, 'path' => array('path', 'file.php')), - array('length' => 32, 'path' => array('path2', 'file2.php')), - array('length' => 123, 'path' => array('file.php')), - ); - $info = array('files' => $files); + $files = [ + ['length' => 12, 'path' => ['path', 'file.php']], + ['length' => 32, 'path' => ['path2', 'file2.php']], + ['length' => 123, 'path' => ['file.php']], + ]; + $info = ['files' => $files]; $this->torrent->setInfo($info); $this->assertEquals(167, $this->torrent->getSize()); } @@ -216,17 +216,17 @@ public function testCreateFromTorrentFileWithLists() { $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_extra_files/extra.torrent'); // we expect an array of arrays, according to the spec - $announceList = array( - array( + $announceList = [ + [ 'http://tracker/', 'http://tracker2/', - 'http://tracker3/' - ) - ); + 'http://tracker3/', + ] + ]; $this->assertSame('http://tracker/', $torrent->getAnnounce()); $this->assertEquals($announceList, $torrent->getAnnounceList()); - $this->assertSame(1, count($torrent->getFileList())); + $this->assertSame('extra', $torrent->getFileList()); } /** @@ -236,14 +236,14 @@ public function testCreateFromTorrentFileWithLists() { public function testCreateFromTorrentFileWithExtra() { $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_extra_files/extra.torrent'); - $webSeeds = array( + $webSeeds = [ 'url-list' => - array( + [ 'http://seed/', 'http://seed2/', - 'http://seed3/' - ) - ); + 'http://seed3/', + ] + ]; $this->assertEquals($webSeeds, $torrent->getExtraMeta()); } @@ -303,7 +303,7 @@ public function testCreateFromPathWhenUsingAFileAsArgument() { public function testSaveTorrent() { $path = __DIR__ . '/_files'; $announce = 'http://tracker/'; - $announceList = array(array('http://tracker2'), array('http://tracker3'));; + $announceList = [['http://tracker2'], ['http://tracker3']]; $comment = 'Some comment'; $createdBy = 'PHPUnit'; $target = tempnam(sys_get_temp_dir(), 'PHP\BitTorrent'); @@ -349,14 +349,13 @@ public function testSaveWithExtra() { $this->fail('Could not create file: ' . $target); } - $extra = array( - 'url-list' => - array( + $extra = [ + 'url-list' => [ 'http://seed/', 'http://seed2/', - 'http://seed3/' - ) - ); + 'http://seed3/', + ], + ]; $torrent = Torrent::createFromPath($path, $announce); $torrent->setExtraMeta($extra) @@ -389,7 +388,7 @@ public function testSaveWithInvalidExtra() { $this->fail('Could not create file: ' . $target); } - $extra = array('announce' => 'http://extratracker'); + $extra = ['announce' => 'http://extratracker']; $torrent = Torrent::createFromPath($path, $announce); $torrent->setExtraMeta($extra) From f530eae9986344713926fd260805d4ca0e7a7190 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Fri, 24 May 2019 14:00:24 +0200 Subject: [PATCH 36/70] Alway return array --- src/Torrent.php | 11 +++-------- tests/TorrentTest.php | 6 ++++-- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/Torrent.php b/src/Torrent.php index 33b9d19..99653ca 100644 --- a/src/Torrent.php +++ b/src/Torrent.php @@ -542,18 +542,13 @@ public function save($filename, EncoderInterface $encoder = null) { /** * Get the files listed in the torrent * - * If the torrent is a multifile torrent, return the files array. If it contains a single file, - * return the name element from the info array. - * - * @return string|array Returns a string if the torrent only contains one file or an array of - * files otherwise. - * @throws RuntimeException + * @return array List of files */ - public function getFileList() { + public function getFileList() : array { $info = $this->getInfoPart(); if (isset($info['length'])) { - return $info['name']; + return [$info['name']]; } return $info['files']; diff --git a/tests/TorrentTest.php b/tests/TorrentTest.php index f4f576e..d988505 100644 --- a/tests/TorrentTest.php +++ b/tests/TorrentTest.php @@ -154,7 +154,9 @@ public function testGetFileListWhenInfoBlockOnlyContainsOneFile() { $name = 'some_filename'; $info = ['length' => 123, 'name' => $name]; $this->torrent->setInfo($info); - $this->assertSame($name, $this->torrent->getFileList()); + $fileList = $this->torrent->getFileList(); + $this->assertCount(1, $fileList); + $this->assertSame($name, $fileList[0]); } /** @@ -226,7 +228,7 @@ public function testCreateFromTorrentFileWithLists() { $this->assertSame('http://tracker/', $torrent->getAnnounce()); $this->assertEquals($announceList, $torrent->getAnnounceList()); - $this->assertSame('extra', $torrent->getFileList()); + $this->assertSame(1, count($torrent->getFileList())); } /** From 8a3b934e4b5523eeb0663f1e2b154c82b431fff4 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Mon, 27 May 2019 07:47:32 +0200 Subject: [PATCH 37/70] Generic cleanup --- src/Decoder.php | 28 ++++------ src/DecoderInterface.php | 2 +- src/Encoder.php | 18 +++--- src/Torrent.php | 117 +++++++++++---------------------------- tests/DecoderTest.php | 3 - 5 files changed, 54 insertions(+), 114 deletions(-) diff --git a/src/Decoder.php b/src/Decoder.php index 5be3ab9..042ffa3 100644 --- a/src/Decoder.php +++ b/src/Decoder.php @@ -7,16 +7,12 @@ class Decoder implements DecoderInterface { private $encoder; public function __construct(EncoderInterface $encoder = null) { - if ($encoder === null) { - $encoder = new Encoder(); - } - - $this->encoder = $encoder; + $this->encoder = $encoder ?? new Encoder(); } public function decodeFile(string $file, bool $strict = false) : array { if (!is_readable($file)) { - throw new InvalidArgumentException('File ' . $file . ' does not exist or can not be read.'); + throw new InvalidArgumentException(sprintf('File %s does not exist or can not be read.', $file)); } $dictionary = $this->decodeDictionary(file_get_contents($file, true)); @@ -33,11 +29,11 @@ public function decodeFile(string $file, bool $strict = false) : array { } public function decode(string $string) { - if ($string[0] === 'i') { + if ('i' === $string[0]) { return $this->decodeInteger($string); - } else if ($string[0] === 'l') { + } else if ('l' === $string[0]) { return $this->decodeList($string); - } else if ($string[0] === 'd') { + } else if ('d' === $string[0]) { return $this->decodeDictionary($string); } else if (preg_match('/^\d+:/', $string)) { return $this->decodeString($string); @@ -47,14 +43,14 @@ public function decode(string $string) { } public function decodeInteger(string $integer) : int { - if ($integer[0] !== 'i' || (!$ePos = strpos($integer, 'e'))) { + if ('i' !== $integer[0] || (!$ePos = strpos($integer, 'e'))) { throw new InvalidArgumentException('Invalid integer. Integers must start wth "i" and end with "e".'); } $integer = substr($integer, 1, ($ePos - 1)); $len = strlen($integer); - if (($integer[0] === '0' && $len > 1) || ($integer[0] === '-' && $integer[1] === '0') || !is_numeric($integer)) { + if (('0' === $integer[0] && $len > 1) || ('-' === $integer[0] && '0' === $integer[1]) || !is_numeric($integer)) { throw new InvalidArgumentException('Invalid integer value.'); } @@ -64,7 +60,7 @@ public function decodeInteger(string $integer) : int { public function decodeString(string $string) : string { $stringParts = explode(':', $string, 2); - if (count($stringParts) !== 2) { + if (2 !== count($stringParts)) { throw new InvalidArgumentException('Invalid string. Strings consist of two parts separated by ":".'); } @@ -79,7 +75,7 @@ public function decodeString(string $string) : string { } public function decodeList(string $list) : array { - if ($list[0] !== 'l') { + if ('l' !== $list[0]) { throw new InvalidArgumentException('Parameter is not an encoded list.'); } @@ -89,7 +85,7 @@ public function decodeList(string $list) : array { $i = 1; while ($i < $length) { - if ($list[$i] === 'e') { + if ('e' === $list[$i]) { break; } @@ -103,7 +99,7 @@ public function decodeList(string $list) : array { } public function decodeDictionary(string $dictionary) : array { - if ($dictionary[0] !== 'd') { + if ('d' !== $dictionary[0]) { throw new InvalidArgumentException('Parameter is not an encoded dictionary.'); } @@ -112,7 +108,7 @@ public function decodeDictionary(string $dictionary) : array { $i = 1; while ($i < $length) { - if ($dictionary[$i] === 'e') { + if ('e' === $dictionary[$i]) { break; } diff --git a/src/DecoderInterface.php b/src/DecoderInterface.php index 4ebcfde..6c4307d 100644 --- a/src/DecoderInterface.php +++ b/src/DecoderInterface.php @@ -16,7 +16,7 @@ interface DecoderInterface { * By default the method does not check for these elements. * * @param string $file Path to the torrent file we want to decode - * @param boolean $strict If set to true this method will check for certain elements in the + * @param bool $strict If set to true this method will check for certain elements in the * dictionary. * @return array Returns the decoded version of the file as an array * @throws InvalidArgumentException diff --git a/src/Encoder.php b/src/Encoder.php index 2739542..164effd 100644 --- a/src/Encoder.php +++ b/src/Encoder.php @@ -48,7 +48,7 @@ public function encode($var) : string { } public function encodeInteger(int $integer) : string { - return 'i' . $integer . 'e'; + return sprintf('i%de', $integer); } public function encodeString(string $string) : string { @@ -56,24 +56,22 @@ public function encodeString(string $string) : string { } public function encodeList(array $list) : string { - $ret = 'l'; + $encodedList = array_map(function($value) { + return $this->encode($value); + }, $list); - foreach ($list as $value) { - $ret .= $this->encode($value); - } - - return $ret . 'e'; + return sprintf('l%se', implode('', $encodedList)); } public function encodeDictionary(array $dictionary) : string { ksort($dictionary); - $ret = 'd'; + $encodedDictionary = ''; foreach ($dictionary as $key => $value) { - $ret .= $this->encodeString((string) $key) . $this->encode($value); + $encodedDictionary .= $this->encodeString((string) $key) . $this->encode($value); } - return $ret . 'e'; + return sprintf('d%se', $encodedDictionary); } } diff --git a/src/Torrent.php b/src/Torrent.php index 99653ca..20704dc 100644 --- a/src/Torrent.php +++ b/src/Torrent.php @@ -26,7 +26,7 @@ class Torrent { * * @var array */ - private $announceList; + private $announceList = []; /** * Optional comment @@ -68,7 +68,7 @@ class Torrent { * * @param string $announceUrl Optional announce URL */ - public function __construct($announceUrl = null) { + public function __construct(string $announceUrl = null) { if ($announceUrl !== null) { $this->setAnnounce($announceUrl); } @@ -84,20 +84,16 @@ public function __construct($announceUrl = null) { */ static public function createFromTorrentFile($path, DecoderInterface $decoder = null) { if (!is_file($path)) { - throw new InvalidArgumentException($path . ' does not exist.'); + throw new InvalidArgumentException(sprintf('%s does not exist.', $path)); } - // Make sure we have a decoder if ($decoder === null) { $decoder = new Decoder(); } $decodedFile = $decoder->decodeFile($path); - - // Create a new torrent $torrent = new static(); - // Populate the object with data from the file if (isset($decodedFile['announce'])) { $torrent->setAnnounce($decodedFile['announce']); unset($decodedFile['announce']); @@ -128,7 +124,6 @@ static public function createFromTorrentFile($path, DecoderInterface $decoder = unset($decodedFile['info']); } - // add any extra meta info fields that were left in this file if (count($decodedFile) > 0) { $torrent->setExtraMeta($decodedFile); } @@ -146,18 +141,13 @@ static public function createFromTorrentFile($path, DecoderInterface $decoder = * @param string $announceUrl URL to the announce * @return Torrent Returns a new instance of this class */ - static public function createFromPath($path, $announceUrl = null) { - // Create a new torrent instance + static public function createFromPath($path, $announceUrl) { $torrent = new static($announceUrl); - - // Initialize array of the files to include in the torrent $files = []; - // Generate an absolute path $absolutePath = realpath($path); $pathIsFile = false; - // See if we have a single file if (false !== $absolutePath && is_file($absolutePath)) { $pathIsFile = true; $files[] = [ @@ -181,32 +171,20 @@ static public function createFromPath($path, $announceUrl = null) { ]; } } else { - throw new InvalidArgumentException('Invalid path: ' . $path); + throw new InvalidArgumentException(sprintf('Invalid path: %s', $path)); } - // Initialize the info part of the torrent $info = [ 'piece length' => pow(2, $torrent->getPieceLengthExp()) ]; - // Initialize the pieces $pieces = []; - // If we only have a single file, get the size of the file and set the name property if ($pathIsFile) { - // Regenerate the path to the file $filePath = dirname($absolutePath); - - // The name of the file in the torrent $info['name'] = $files[0]['filename']; - - // The size of the file $info['length'] = $files[0]['filesize']; - - // The current position in the file $position = 0; - - // Open the file $fp = fopen($filePath . DIRECTORY_SEPARATOR . $files[0]['filename'], 'rb'); while ($position < $info['length']) { @@ -220,15 +198,12 @@ static public function createFromPath($path, $announceUrl = null) { } } - // Close the file handle fclose($fp); $pieces = implode('', $pieces); } else { - // The name of the directory in the torrent $info['name'] = basename($absolutePath); - // Sort the filelist to mimic btmakemetafile usort($files, function($a, $b) { if ($a['filename'] < $b['filename']) { return -1; @@ -239,7 +214,6 @@ static public function createFromPath($path, $announceUrl = null) { return 0; }); - // Initialize some helper variables for the hashing or the parts of each file $part = ''; $done = 0; @@ -255,13 +229,9 @@ static public function createFromPath($path, $announceUrl = null) { 'path' => explode(DIRECTORY_SEPARATOR, $filename) ]; - // Reset the position in the current file $position = 0; - - // Open the current file $fp = fopen($absolutePath . DIRECTORY_SEPARATOR . $filename, 'rb'); - // Loop through the file while ($position < $filesize) { $bytes = min(($filesize - $position), ($info['piece length'] - $done)); $part .= fread($fp, $bytes); @@ -269,7 +239,6 @@ static public function createFromPath($path, $announceUrl = null) { $done += $bytes; $position += $bytes; - // We have a piece. Add it to the array and reset the helper variables if ($done === $info['piece length']) { $pieces[] = sha1($part, true); $part = ''; @@ -277,26 +246,18 @@ static public function createFromPath($path, $announceUrl = null) { } } - // Close the file handle fclose($fp); } - // If there is a part still not hashed then add it to the pieces array if ($done > 0) { $pieces[] = sha1($part, true); } - // Make a string of the pieces $pieces = implode('', $pieces); } - // Store the pieces in the $info array $info['pieces'] = $pieces; - - // Sort the info array ksort($info); - - // Set the info $torrent->setInfo($info); return $torrent; @@ -306,10 +267,10 @@ static public function createFromPath($path, $announceUrl = null) { * Set the piece length exponent * * @param int $pieceLengthExp The exponent to set - * @return Torrent Returns self for a fluent interface + * @return self Returns self for a fluent interface */ - public function setPieceLengthExp($pieceLengthExp) { - $this->pieceLengthExp = (int) $pieceLengthExp; + public function setPieceLengthExp(int $pieceLengthExp) : self { + $this->pieceLengthExp = $pieceLengthExp; return $this; } @@ -320,7 +281,7 @@ public function setPieceLengthExp($pieceLengthExp) { * @return int Returns the piece length exponent used when creating a torrent instance from a * path */ - public function getPieceLengthExp() { + public function getPieceLengthExp() : int { return $this->pieceLengthExp; } @@ -328,9 +289,9 @@ public function getPieceLengthExp() { * Set the announce URL * * @param string $announceUrl The URL to set - * @return Torrent Returns self for a fluent interface + * @return self Returns self for a fluent interface */ - public function setAnnounce($announceUrl) { + public function setAnnounce(string $announceUrl) : self { $this->announce = $announceUrl; return $this; @@ -341,7 +302,7 @@ public function setAnnounce($announceUrl) { * * @return string Returns the URL to the tracker (if set) */ - public function getAnnounce() { + public function getAnnounce() : ?string { return $this->announce; } @@ -349,9 +310,9 @@ public function getAnnounce() { * Set the announce list * * @param array $announceList The array of URLs to set - * @return Torrent Returns self for a fluent interface + * @return self Returns self for a fluent interface */ - public function setAnnounceList(array $announceList) { + public function setAnnounceList(array $announceList) : self { $this->announceList = $announceList; return $this; @@ -362,7 +323,7 @@ public function setAnnounceList(array $announceList) { * * @return array Returns the URL to the tracker (if set) */ - public function getAnnounceList() { + public function getAnnounceList() : ?array { return $this->announceList; } @@ -485,7 +446,7 @@ public function getExtraMeta() { */ public function save($filename, EncoderInterface $encoder = null) { if (!is_writable($filename) && !is_writable(dirname($filename))) { - throw new InvalidArgumentException('Could not open file "' . $filename . '" for writing.'); + throw new InvalidArgumentException(sprintf('Could not open file "%s" for writing.', $filename)); } $info = $this->getInfoPart(); @@ -530,11 +491,7 @@ public function save($filename, EncoderInterface $encoder = null) { } } - // Create the encoded dictionary - $dictionary = $encoder->encodeDictionary($torrent); - - // Write the encoded data to the file - file_put_contents($filename, $dictionary); + file_put_contents($filename, $encoder->encodeDictionary($torrent)); return $this; } @@ -542,7 +499,7 @@ public function save($filename, EncoderInterface $encoder = null) { /** * Get the files listed in the torrent * - * @return array List of files + * @return string[] List of files */ public function getFileList() : array { $info = $this->getInfoPart(); @@ -558,12 +515,10 @@ public function getFileList() : array { * Get the size of the files in the torrent * * @return int Returns the size of the files in the torrent in bytes - * @throws RuntimeException */ - public function getSize() { + public function getSize() : int { $info = $this->getInfoPart(); - // If the length element is set, return that one. If not, loop through the files and generate the total if (isset($info['length'])) { return $info['length']; } @@ -582,36 +537,30 @@ public function getSize() { * Get the name that the content will be saved as * * @return string The name of the torrent - * @throws RuntimeException */ - public function getName() { - $info = $this->getInfoPart(); - - return $info['name']; + public function getName() : string { + return $this->getInfoPart()['name']; } /** * Get the hash of the torrent file * - * @param boolean $raw Set to true to return the raw 20-byte hash + * @param bool $raw Set to true to return the raw 20-byte hash * @return string The torrent hash - * @throws RuntimeException */ - public function getHash($raw = false) { - $info = $this->getInfoPart(); - - $encoder = new Encoder(); - - return sha1($encoder->encodeDictionary($info), $raw); + public function getHash(bool $raw = false) : string { + return sha1( + (new Encoder())->encodeDictionary($this->getInfoPart()), + $raw + ); } /** * Get the urlencoded raw hash of the torrent file * * @return string The torrent hash - * @throws RuntimeException */ - public function getEncodedHash() { + public function getEncodedHash() : string { return urlencode($this->getHash(true)); } @@ -621,10 +570,10 @@ public function getEncodedHash() { * @return array * @throws RuntimeException */ - private function getInfoPart() { + private function getInfoPart() : array { $info = $this->getInfo(); - if ($info === null) { + if (null === $info) { throw new RuntimeException('The info part of the torrent is not set.'); } @@ -634,11 +583,11 @@ private function getInfoPart() { /** * Check if the torrent is private or not (via the optional private flag) * - * @return boolean + * @return bool */ - public function isPrivate() { + public function isPrivate() : bool { $info = $this->getInfoPart(); - return (isset($info['private']) && $info['private'] === 1) ? true : false; + return (isset($info['private']) && 1 === $info['private']) ? true : false; } } diff --git a/tests/DecoderTest.php b/tests/DecoderTest.php index 8864abe..5b8922b 100644 --- a/tests/DecoderTest.php +++ b/tests/DecoderTest.php @@ -9,9 +9,6 @@ class DecoderTest extends TestCase { private $decoder; - /** - * Set up the decoder - */ public function setUp() { $this->decoder = new Decoder(); } From f7d34e3fd5dab12b804d6b97cc3df57948182559 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Mon, 2 Sep 2019 18:20:50 +0200 Subject: [PATCH 38/70] Use GitHub Actions instead of Travis CI --- .github/workflows/default.yml | 19 ++ .travis.yml | 12 - composer.json | 4 +- composer.lock | 463 ++++++++++++++++++++-------------- 4 files changed, 301 insertions(+), 197 deletions(-) create mode 100644 .github/workflows/default.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml new file mode 100644 index 0000000..af41a0f --- /dev/null +++ b/.github/workflows/default.yml @@ -0,0 +1,19 @@ +name: CI + +on: [push] + +jobs: + build: + runs-on: ubuntu-18.04 + + steps: + - uses: actions/checkout@v1 + + - name: Dump PHP version + run: php -v + + - name: Install Barrel API Client dependencies through Composer + run: composer install --prefer-dist --no-progress --no-suggest + + - name: Run CI steps + run: composer run ci \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index f3e54af..0000000 --- a/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: php - -php: - - 7.1 - - 7.2 - - 7.3 - -before_script: - - composer install -n --prefer-dist - -script: - - composer ci diff --git a/composer.json b/composer.json index d9f85e6..28efb14 100644 --- a/composer.json +++ b/composer.json @@ -15,12 +15,12 @@ } ], "require": { - "php": ">=7.1" + "php": ">=7.2" }, "require-dev": { "phpunit/phpunit": "^7.0", "phploc/phploc": "^4.0", - "phpstan/phpstan": "^0.11.7" + "phpstan/phpstan": "^0.11" }, "support": { "source": "https://github.com/christeredvartsen/php-bittorrent", diff --git a/composer.lock b/composer.lock index e612640..3e66d68 100644 --- a/composer.lock +++ b/composer.lock @@ -4,21 +4,21 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "ddacbc9e11aef638f33c440a178bb091", + "content-hash": "8fc8f677b2d9c240dc10b5d3317a3f95", "packages": [], "packages-dev": [ { "name": "composer/xdebug-handler", - "version": "1.3.2", + "version": "1.3.3", "source": { "type": "git", "url": "https://github.com/composer/xdebug-handler.git", - "reference": "d17708133b6c276d6e42ef887a877866b909d892" + "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/d17708133b6c276d6e42ef887a877866b909d892", - "reference": "d17708133b6c276d6e42ef887a877866b909d892", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/46867cbf8ca9fb8d60c506895449eb799db1184f", + "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f", "shasum": "" }, "require": { @@ -49,7 +49,7 @@ "Xdebug", "performance" ], - "time": "2019-01-28T20:25:53+00:00" + "time": "2019-05-27T17:52:04+00:00" }, { "name": "doctrine/instantiator", @@ -160,16 +160,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.9.1", + "version": "1.9.3", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72" + "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", - "reference": "e6828efaba2c9b79f4499dae1d66ef8bfa7b2b72", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea", + "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea", "shasum": "" }, "require": { @@ -204,7 +204,7 @@ "object", "object graph" ], - "time": "2019-04-07T13:18:21+00:00" + "time": "2019-08-09T12:45:53+00:00" }, { "name": "nette/bootstrap", @@ -281,16 +281,16 @@ }, { "name": "nette/di", - "version": "v3.0.0", + "version": "v3.0.1", "source": { "type": "git", "url": "https://github.com/nette/di.git", - "reference": "19d83539245aaacb59470828919182411061841f" + "reference": "4aff517a1c6bb5c36fa09733d4cea089f529de6d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/di/zipball/19d83539245aaacb59470828919182411061841f", - "reference": "19d83539245aaacb59470828919182411061841f", + "url": "https://api.github.com/repos/nette/di/zipball/4aff517a1c6bb5c36fa09733d4cea089f529de6d", + "reference": "4aff517a1c6bb5c36fa09733d4cea089f529de6d", "shasum": "" }, "require": { @@ -350,7 +350,7 @@ "nette", "static" ], - "time": "2019-04-03T19:35:46+00:00" + "time": "2019-08-07T12:11:33+00:00" }, { "name": "nette/finder", @@ -477,16 +477,16 @@ }, { "name": "nette/php-generator", - "version": "v3.2.2", + "version": "v3.2.3", "source": { "type": "git", "url": "https://github.com/nette/php-generator.git", - "reference": "acff8b136fad84b860a626d133e791f95781f9f5" + "reference": "aea6e81437bb238e5f0e5b5ce06337433908e63b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/php-generator/zipball/acff8b136fad84b860a626d133e791f95781f9f5", - "reference": "acff8b136fad84b860a626d133e791f95781f9f5", + "url": "https://api.github.com/repos/nette/php-generator/zipball/aea6e81437bb238e5f0e5b5ce06337433908e63b", + "reference": "aea6e81437bb238e5f0e5b5ce06337433908e63b", "shasum": "" }, "require": { @@ -532,7 +532,7 @@ "php", "scaffolding" ], - "time": "2019-03-15T03:41:13+00:00" + "time": "2019-07-05T13:01:56+00:00" }, { "name": "nette/robot-loader", @@ -731,16 +731,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.2.1", + "version": "v4.2.4", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "5221f49a608808c1e4d436df32884cbc1b821ac0" + "reference": "97e59c7a16464196a8b9c77c47df68e4a39a45c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/5221f49a608808c1e4d436df32884cbc1b821ac0", - "reference": "5221f49a608808c1e4d436df32884cbc1b821ac0", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/97e59c7a16464196a8b9c77c47df68e4a39a45c4", + "reference": "97e59c7a16464196a8b9c77c47df68e4a39a45c4", "shasum": "" }, "require": { @@ -748,7 +748,7 @@ "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "^6.5 || ^7.0" + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0" }, "bin": [ "bin/php-parse" @@ -778,7 +778,7 @@ "parser", "php" ], - "time": "2019-02-16T20:54:15+00:00" + "time": "2019-09-01T07:51:21+00:00" }, { "name": "ocramius/package-versions", @@ -1135,16 +1135,16 @@ }, { "name": "phpspec/prophecy", - "version": "1.8.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" + "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", - "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76", + "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76", "shasum": "" }, "require": { @@ -1165,8 +1165,8 @@ } }, "autoload": { - "psr-0": { - "Prophecy\\": "src/" + "psr-4": { + "Prophecy\\": "src/Prophecy" } }, "notification-url": "https://packagist.org/downloads/", @@ -1194,20 +1194,20 @@ "spy", "stub" ], - "time": "2018-08-05T17:53:17+00:00" + "time": "2019-06-13T12:50:23+00:00" }, { "name": "phpstan/phpdoc-parser", - "version": "0.3.3", + "version": "0.3.5", "source": { "type": "git", "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "472d3161d289f652713a5e353532fa4592663a57" + "reference": "8c4ef2aefd9788238897b678a985e1d5c8df6db4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/472d3161d289f652713a5e353532fa4592663a57", - "reference": "472d3161d289f652713a5e353532fa4592663a57", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/8c4ef2aefd9788238897b678a985e1d5c8df6db4", + "reference": "8c4ef2aefd9788238897b678a985e1d5c8df6db4", "shasum": "" }, "require": { @@ -1241,20 +1241,20 @@ "MIT" ], "description": "PHPDoc parser with support for nullable, intersection and generic types", - "time": "2019-04-23T20:26:19+00:00" + "time": "2019-06-07T19:13:52+00:00" }, { "name": "phpstan/phpstan", - "version": "0.11.7", + "version": "0.11.15", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "32d87d746c70785f78d239855782d27cde0eb6ee" + "reference": "1be5b3a706db16ac472a4c40ec03cf4c810b118d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/32d87d746c70785f78d239855782d27cde0eb6ee", - "reference": "32d87d746c70785f78d239855782d27cde0eb6ee", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/1be5b3a706db16ac472a4c40ec03cf4c810b118d", + "reference": "1be5b3a706db16ac472a4c40ec03cf4c810b118d", "shasum": "" }, "require": { @@ -1265,9 +1265,9 @@ "nette/robot-loader": "^3.0.1", "nette/schema": "^1.0", "nette/utils": "^2.4.5 || ^3.0", - "nikic/php-parser": "^4.0.2", + "nikic/php-parser": "^4.2.3", "php": "~7.1", - "phpstan/phpdoc-parser": "^0.3", + "phpstan/phpdoc-parser": "^0.3.5", "symfony/console": "~3.2 || ~4.0", "symfony/finder": "~3.2 || ~4.0" }, @@ -1275,11 +1275,12 @@ "symfony/console": "3.4.16 || 4.1.5" }, "require-dev": { - "brianium/paratest": "^2.0", + "brianium/paratest": "^2.0 || ^3.0", "consistence/coding-standard": "^3.5", "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4", "ext-intl": "*", "ext-mysqli": "*", + "ext-simplexml": "*", "ext-soap": "*", "ext-zip": "*", "jakub-onderka/php-parallel-lint": "^1.0", @@ -1289,7 +1290,7 @@ "phpstan/phpstan-php-parser": "^0.11", "phpstan/phpstan-phpunit": "^0.11", "phpstan/phpstan-strict-rules": "^0.11", - "phpunit/phpunit": "^7.0", + "phpunit/phpunit": "^7.5.14 || ^8.0", "slevomat/coding-standard": "^4.7.2", "squizlabs/php_codesniffer": "^3.3.2" }, @@ -1315,7 +1316,7 @@ "MIT" ], "description": "PHPStan - PHP Static Analysis Tool", - "time": "2019-05-19T17:36:42+00:00" + "time": "2019-08-18T20:51:53+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1473,16 +1474,16 @@ }, { "name": "phpunit/php-timer", - "version": "2.1.1", + "version": "2.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059" + "reference": "1038454804406b0b5f5f520358e78c1c2f71501e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/8b389aebe1b8b0578430bda0c7c95a829608e059", - "reference": "8b389aebe1b8b0578430bda0c7c95a829608e059", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/1038454804406b0b5f5f520358e78c1c2f71501e", + "reference": "1038454804406b0b5f5f520358e78c1c2f71501e", "shasum": "" }, "require": { @@ -1518,20 +1519,20 @@ "keywords": [ "timer" ], - "time": "2019-02-20T10:12:59+00:00" + "time": "2019-06-07T04:22:29+00:00" }, { "name": "phpunit/php-token-stream", - "version": "3.0.1", + "version": "3.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18" + "reference": "e899757bb3df5ff6e95089132f32cd59aac2220a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18", - "reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e899757bb3df5ff6e95089132f32cd59aac2220a", + "reference": "e899757bb3df5ff6e95089132f32cd59aac2220a", "shasum": "" }, "require": { @@ -1544,7 +1545,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.1-dev" } }, "autoload": { @@ -1567,20 +1568,20 @@ "keywords": [ "tokenizer" ], - "time": "2018-10-30T05:52:18+00:00" + "time": "2019-07-25T05:29:42+00:00" }, { "name": "phpunit/phpunit", - "version": "7.5.11", + "version": "7.5.15", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "64cb33f5b520da490a7b13149d39b43cf3c890c6" + "reference": "d79c053d972856b8b941bb233e39dc521a5093f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/64cb33f5b520da490a7b13149d39b43cf3c890c6", - "reference": "64cb33f5b520da490a7b13149d39b43cf3c890c6", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d79c053d972856b8b941bb233e39dc521a5093f0", + "reference": "d79c053d972856b8b941bb233e39dc521a5093f0", "shasum": "" }, "require": { @@ -1651,7 +1652,56 @@ "testing", "xunit" ], - "time": "2019-05-14T04:53:02+00:00" + "time": "2019-08-21T07:05:16+00:00" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" }, { "name": "psr/log", @@ -1920,16 +1970,16 @@ }, { "name": "sebastian/exporter", - "version": "3.1.0", + "version": "3.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" + "reference": "06a9a5947f47b3029d76118eb5c22802e5869687" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", - "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/06a9a5947f47b3029d76118eb5c22802e5869687", + "reference": "06a9a5947f47b3029d76118eb5c22802e5869687", "shasum": "" }, "require": { @@ -1956,6 +2006,10 @@ "BSD-3-Clause" ], "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" @@ -1964,17 +2018,13 @@ "name": "Volker Dusch", "email": "github@wallbash.com" }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, { "name": "Adam Harvey", "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" } ], "description": "Provides the functionality to export PHP variables for visualization", @@ -1983,7 +2033,7 @@ "export", "exporter" ], - "time": "2017-04-03T13:19:02+00:00" + "time": "2019-08-11T12:43:14+00:00" }, { "name": "sebastian/finder-facade", @@ -2307,25 +2357,27 @@ }, { "name": "symfony/console", - "version": "v4.2.8", + "version": "v4.3.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "e2840bb38bddad7a0feaf85931e38fdcffdb2f81" + "reference": "de63799239b3881b8a08f8481b22348f77ed7b36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/e2840bb38bddad7a0feaf85931e38fdcffdb2f81", - "reference": "e2840bb38bddad7a0feaf85931e38fdcffdb2f81", + "url": "https://api.github.com/repos/symfony/console/zipball/de63799239b3881b8a08f8481b22348f77ed7b36", + "reference": "de63799239b3881b8a08f8481b22348f77ed7b36", "shasum": "" }, "require": { "php": "^7.1.3", - "symfony/contracts": "^1.0", - "symfony/polyfill-mbstring": "~1.0" + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.8", + "symfony/service-contracts": "^1.1" }, "conflict": { "symfony/dependency-injection": "<3.4", + "symfony/event-dispatcher": "<4.3", "symfony/process": "<3.3" }, "provide": { @@ -2335,9 +2387,10 @@ "psr/log": "~1.0", "symfony/config": "~3.4|~4.0", "symfony/dependency-injection": "~3.4|~4.0", - "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/event-dispatcher": "^4.3", "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.4|~4.0" + "symfony/process": "~3.4|~4.0", + "symfony/var-dumper": "^4.3" }, "suggest": { "psr/log": "For using the console logger", @@ -2348,7 +2401,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.2-dev" + "dev-master": "4.3-dev" } }, "autoload": { @@ -2375,51 +2428,37 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2019-04-08T14:23:48+00:00" + "time": "2019-08-26T08:26:39+00:00" }, { - "name": "symfony/contracts", - "version": "v1.1.0", + "name": "symfony/finder", + "version": "v4.3.4", "source": { "type": "git", - "url": "https://github.com/symfony/contracts.git", - "reference": "d3636025e8253c6144358ec0a62773cae588395b" + "url": "https://github.com/symfony/finder.git", + "reference": "86c1c929f0a4b24812e1eb109262fc3372c8e9f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/contracts/zipball/d3636025e8253c6144358ec0a62773cae588395b", - "reference": "d3636025e8253c6144358ec0a62773cae588395b", + "url": "https://api.github.com/repos/symfony/finder/zipball/86c1c929f0a4b24812e1eb109262fc3372c8e9f2", + "reference": "86c1c929f0a4b24812e1eb109262fc3372c8e9f2", "shasum": "" }, "require": { "php": "^7.1.3" }, - "require-dev": { - "psr/cache": "^1.0", - "psr/container": "^1.0", - "symfony/polyfill-intl-idn": "^1.10" - }, - "suggest": { - "psr/cache": "When using the Cache contracts", - "psr/container": "When using the Service contracts", - "symfony/cache-contracts-implementation": "", - "symfony/event-dispatcher-implementation": "", - "symfony/http-client-contracts-implementation": "", - "symfony/service-contracts-implementation": "", - "symfony/translation-contracts-implementation": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "4.3-dev" } }, "autoload": { "psr-4": { - "Symfony\\Contracts\\": "" + "Symfony\\Component\\Finder\\": "" }, "exclude-from-classmap": [ - "**/Tests/" + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2428,55 +2467,50 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "A set of abstractions extracted out of the Symfony components", + "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "time": "2019-04-27T14:29:50+00:00" + "time": "2019-08-14T12:26:46+00:00" }, { - "name": "symfony/finder", - "version": "v4.2.8", + "name": "symfony/polyfill-ctype", + "version": "v1.12.0", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "e45135658bd6c14b61850bf131c4f09a55133f69" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/e45135658bd6c14b61850bf131c4f09a55133f69", - "reference": "e45135658bd6c14b61850bf131c4f09a55133f69", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.2-dev" + "dev-master": "1.12-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Finder\\": "" + "Symfony\\Polyfill\\Ctype\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "files": [ + "bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2485,47 +2519,53 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Finder Component", + "description": "Symfony polyfill for ctype functions", "homepage": "https://symfony.com", - "time": "2019-04-06T13:51:08+00:00" + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2019-08-06T08:03:45+00:00" }, { - "name": "symfony/polyfill-ctype", - "version": "v1.11.0", + "name": "symfony/polyfill-mbstring", + "version": "v1.12.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "82ebae02209c21113908c229e9883c419720738a" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/82ebae02209c21113908c229e9883c419720738a", - "reference": "82ebae02209c21113908c229e9883c419720738a", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17", + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17", "shasum": "" }, "require": { "php": ">=5.3.3" }, "suggest": { - "ext-ctype": "For best performance" + "ext-mbstring": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Ctype\\": "" + "Symfony\\Polyfill\\Mbstring\\": "" }, "files": [ "bootstrap.php" @@ -2537,56 +2577,57 @@ ], "authors": [ { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { - "name": "Gert de Pagter", - "email": "BackEndTea@gmail.com" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for ctype functions", + "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "ctype", + "mbstring", "polyfill", - "portable" + "portable", + "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.11.0", + "name": "symfony/polyfill-php73", + "version": "v1.12.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609" + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fe5e94c604826c35a32fa832f35bd036b6799609", - "reference": "fe5e94c604826c35a32fa832f35bd036b6799609", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/2ceb49eaccb9352bff54d22570276bb75ba4a188", + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "suggest": { - "ext-mbstring": "For best performance" - }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11-dev" + "dev-master": "1.12-dev" } }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" + "Symfony\\Polyfill\\Php73\\": "" }, "files": [ "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -2603,16 +2644,73 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "mbstring", "polyfill", "portable", "shim" ], - "time": "2019-02-06T07:57:58+00:00" + "time": "2019-08-06T08:03:45+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v1.1.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "ea7263d6b6d5f798b56a45a5b8d686725f2719a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ea7263d6b6d5f798b56a45a5b8d686725f2719a3", + "reference": "ea7263d6b6d5f798b56a45a5b8d686725f2719a3", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/container": "^1.0" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-08-20T14:44:19+00:00" }, { "name": "theseer/fdomdocument", @@ -2656,16 +2754,16 @@ }, { "name": "theseer/tokenizer", - "version": "1.1.2", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8" + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/1c42705be2b6c1de5904f8afacef5895cab44bf8", - "reference": "1c42705be2b6c1de5904f8afacef5895cab44bf8", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/11336f6f84e16a720dae9d8e6ed5019efa85a0f9", + "reference": "11336f6f84e16a720dae9d8e6ed5019efa85a0f9", "shasum": "" }, "require": { @@ -2687,25 +2785,25 @@ "authors": [ { "name": "Arne Blankerts", - "email": "arne@blankerts.de", - "role": "Developer" + "role": "Developer", + "email": "arne@blankerts.de" } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", - "time": "2019-04-04T09:56:43+00:00" + "time": "2019-06-13T22:48:21+00:00" }, { "name": "webmozart/assert", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9" + "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/83e253c8e0be5b0257b881e1827274667c5c17a9", - "reference": "83e253c8e0be5b0257b881e1827274667c5c17a9", + "url": "https://api.github.com/repos/webmozart/assert/zipball/88e6d84706d09a236046d686bbea96f07b3a34f4", + "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4", "shasum": "" }, "require": { @@ -2713,8 +2811,7 @@ "symfony/polyfill-ctype": "^1.8" }, "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" + "phpunit/phpunit": "^4.8.36 || ^7.5.13" }, "type": "library", "extra": { @@ -2743,7 +2840,7 @@ "check", "validate" ], - "time": "2018-12-25T11:19:39+00:00" + "time": "2019-08-24T08:43:50+00:00" } ], "aliases": [], @@ -2752,7 +2849,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=7.1" + "php": ">=7.2" }, "platform-dev": [] } From 907e7e11e079166f75e8a3562f8926d1cf13c048 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Mon, 2 Sep 2019 19:36:53 +0200 Subject: [PATCH 39/70] Update deps --- composer.json | 4 +- composer.lock | 158 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 105 insertions(+), 57 deletions(-) diff --git a/composer.json b/composer.json index 28efb14..fec6f56 100644 --- a/composer.json +++ b/composer.json @@ -18,8 +18,8 @@ "php": ">=7.2" }, "require-dev": { - "phpunit/phpunit": "^7.0", - "phploc/phploc": "^4.0", + "phpunit/phpunit": "^8.0", + "phploc/phploc": "^5.0", "phpstan/phpstan": "^0.11" }, "support": { diff --git a/composer.lock b/composer.lock index 3e66d68..db9643a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "8fc8f677b2d9c240dc10b5d3317a3f95", + "content-hash": "2ff19b93a3a486779e2d20c09131cee3", "packages": [], "packages-dev": [ { @@ -1086,23 +1086,23 @@ }, { "name": "phploc/phploc", - "version": "4.0.1", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phploc.git", - "reference": "6a8a9416517b82d6326ac9c2d040ad53c13654eb" + "reference": "5b714ccb7cb8ca29ccf9caf6eb1aed0131d3a884" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phploc/zipball/6a8a9416517b82d6326ac9c2d040ad53c13654eb", - "reference": "6a8a9416517b82d6326ac9c2d040ad53c13654eb", + "url": "https://api.github.com/repos/sebastianbergmann/phploc/zipball/5b714ccb7cb8ca29ccf9caf6eb1aed0131d3a884", + "reference": "5b714ccb7cb8ca29ccf9caf6eb1aed0131d3a884", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0", + "php": "^7.2", "sebastian/finder-facade": "^1.1", "sebastian/version": "^2.0", - "symfony/console": "^2.7|^3.0|^4.0" + "symfony/console": "^4.0" }, "bin": [ "phploc" @@ -1110,7 +1110,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -1131,7 +1131,7 @@ ], "description": "A tool for quickly measuring the size of a PHP project.", "homepage": "https://github.com/sebastianbergmann/phploc", - "time": "2017-11-18T17:35:43+00:00" + "time": "2019-03-16T10:41:19+00:00" }, { "name": "phpspec/prophecy", @@ -1320,40 +1320,40 @@ }, { "name": "phpunit/php-code-coverage", - "version": "6.1.4", + "version": "7.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d" + "reference": "7743bbcfff2a907e9ee4a25be13d0f8ec5e73800" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", - "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7743bbcfff2a907e9ee4a25be13d0f8ec5e73800", + "reference": "7743bbcfff2a907e9ee4a25be13d0f8ec5e73800", "shasum": "" }, "require": { "ext-dom": "*", "ext-xmlwriter": "*", - "php": "^7.1", - "phpunit/php-file-iterator": "^2.0", + "php": "^7.2", + "phpunit/php-file-iterator": "^2.0.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.0", + "phpunit/php-token-stream": "^3.1.0", "sebastian/code-unit-reverse-lookup": "^1.0.1", - "sebastian/environment": "^3.1 || ^4.0", + "sebastian/environment": "^4.2.2", "sebastian/version": "^2.0.1", - "theseer/tokenizer": "^1.1" + "theseer/tokenizer": "^1.1.3" }, "require-dev": { - "phpunit/phpunit": "^7.0" + "phpunit/phpunit": "^8.2.2" }, "suggest": { - "ext-xdebug": "^2.6.0" + "ext-xdebug": "^2.7.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "6.1-dev" + "dev-master": "7.0-dev" } }, "autoload": { @@ -1379,7 +1379,7 @@ "testing", "xunit" ], - "time": "2018-10-31T16:06:48+00:00" + "time": "2019-07-25T05:31:54+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1572,53 +1572,52 @@ }, { "name": "phpunit/phpunit", - "version": "7.5.15", + "version": "8.3.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "d79c053d972856b8b941bb233e39dc521a5093f0" + "reference": "e31cce0cf4499c0ccdbbb211a3280d36ab341e36" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d79c053d972856b8b941bb233e39dc521a5093f0", - "reference": "d79c053d972856b8b941bb233e39dc521a5093f0", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e31cce0cf4499c0ccdbbb211a3280d36ab341e36", + "reference": "e31cce0cf4499c0ccdbbb211a3280d36ab341e36", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.1", + "doctrine/instantiator": "^1.2.0", "ext-dom": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", "ext-xml": "*", - "myclabs/deep-copy": "^1.7", - "phar-io/manifest": "^1.0.2", - "phar-io/version": "^2.0", - "php": "^7.1", - "phpspec/prophecy": "^1.7", - "phpunit/php-code-coverage": "^6.0.7", - "phpunit/php-file-iterator": "^2.0.1", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.9.1", + "phar-io/manifest": "^1.0.3", + "phar-io/version": "^2.0.1", + "php": "^7.2", + "phpspec/prophecy": "^1.8.1", + "phpunit/php-code-coverage": "^7.0.7", + "phpunit/php-file-iterator": "^2.0.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-timer": "^2.1", - "sebastian/comparator": "^3.0", - "sebastian/diff": "^3.0", - "sebastian/environment": "^4.0", - "sebastian/exporter": "^3.1", - "sebastian/global-state": "^2.0", + "phpunit/php-timer": "^2.1.2", + "sebastian/comparator": "^3.0.2", + "sebastian/diff": "^3.0.2", + "sebastian/environment": "^4.2.2", + "sebastian/exporter": "^3.1.0", + "sebastian/global-state": "^3.0.0", "sebastian/object-enumerator": "^3.0.3", - "sebastian/resource-operations": "^2.0", + "sebastian/resource-operations": "^2.0.1", + "sebastian/type": "^1.1.3", "sebastian/version": "^2.0.1" }, - "conflict": { - "phpunit/phpunit-mock-objects": "*" - }, "require-dev": { "ext-pdo": "*" }, "suggest": { "ext-soap": "*", "ext-xdebug": "*", - "phpunit/php-invoker": "^2.0" + "phpunit/php-invoker": "^2.0.0" }, "bin": [ "phpunit" @@ -1626,7 +1625,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "7.5-dev" + "dev-master": "8.3-dev" } }, "autoload": { @@ -1652,7 +1651,7 @@ "testing", "xunit" ], - "time": "2019-08-21T07:05:16+00:00" + "time": "2019-08-11T06:56:55+00:00" }, { "name": "psr/container", @@ -2076,23 +2075,26 @@ }, { "name": "sebastian/global-state", - "version": "2.0.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4" + "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", - "reference": "e8ba02eed7bbbb9e59e43dedd3dddeff4a56b0c4", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4", + "reference": "edf8a461cf1d4005f19fb0b6b8b95a9f7fa0adc4", "shasum": "" }, "require": { - "php": "^7.0" + "php": "^7.2", + "sebastian/object-reflector": "^1.1.1", + "sebastian/recursion-context": "^3.0" }, "require-dev": { - "phpunit/phpunit": "^6.0" + "ext-dom": "*", + "phpunit/phpunit": "^8.0" }, "suggest": { "ext-uopz": "*" @@ -2100,7 +2102,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -2123,7 +2125,7 @@ "keywords": [ "global state" ], - "time": "2017-04-27T15:39:26+00:00" + "time": "2019-02-01T05:30:01+00:00" }, { "name": "sebastian/object-enumerator", @@ -2312,6 +2314,52 @@ "homepage": "https://www.github.com/sebastianbergmann/resource-operations", "time": "2018-10-04T04:07:39+00:00" }, + { + "name": "sebastian/type", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/3aaaa15fa71d27650d62a948be022fe3b48541a3", + "reference": "3aaaa15fa71d27650d62a948be022fe3b48541a3", + "shasum": "" + }, + "require": { + "php": "^7.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "time": "2019-07-02T08:10:15+00:00" + }, { "name": "sebastian/version", "version": "2.0.1", From 97e46d36203de194853c796458c77053277495bb Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Mon, 2 Sep 2019 19:48:48 +0200 Subject: [PATCH 40/70] Update test case --- tests/DecoderTest.php | 126 ++++++++++++++---------------------------- 1 file changed, 43 insertions(+), 83 deletions(-) diff --git a/tests/DecoderTest.php b/tests/DecoderTest.php index 5b8922b..0e94a3b 100644 --- a/tests/DecoderTest.php +++ b/tests/DecoderTest.php @@ -1,6 +1,7 @@ decoder = new Decoder(); } - /** - * Data provider - * - * @return array[] - */ public function getDecodeIntegerData() : array { return [ ['i1e', 1], @@ -29,18 +25,11 @@ public function getDecodeIntegerData() : array { /** * @dataProvider getDecodeIntegerData * @covers ::decodeInteger - * @param string $encoded - * @param int $value */ - public function testDecoderInteger(string $encoded, int $value) { + public function testDecoderInteger(string $encoded, int $value) : void { $this->assertEquals($value, $this->decoder->decodeInteger($encoded)); } - /** - * Data provider - * - * @return array[] - */ public function getDecodeInvalidIntegerData() : array { return [ ['i01e'], @@ -52,37 +41,31 @@ public function getDecodeInvalidIntegerData() : array { /** * @dataProvider getDecodeInvalidIntegerData * @covers ::decodeInteger - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Invalid integer value. - * @param string $value */ - public function testDecodeInvalidInteger(string $value) { + public function testDecodeInvalidInteger(string $value) : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid integer value.'); $this->decoder->decodeInteger($value); } /** * @covers ::decodeInteger - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Invalid integer. Integers must start wth "i" and end with "e". */ - public function testDecodeStringAsInteger() { + public function testDecodeStringAsInteger() : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid integer. Integers must start wth "i" and end with "e".'); $this->decoder->decodeInteger('4:spam'); } /** * @covers ::decodeInteger - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Invalid integer. Integers must start wth "i" and end with "e". */ - public function testDecodePartialInteger() { + public function testDecodePartialInteger() : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid integer. Integers must start wth "i" and end with "e".'); $this->decoder->decodeInteger('i10'); } - /** - * Data provider - * - * @return array[] - */ public function getDecodeStringData() : array { return [ ['4:spam', 'spam'], @@ -94,36 +77,29 @@ public function getDecodeStringData() : array { /** * @dataProvider getDecodeStringData * @covers ::decodeString - * @param string $encoded - * @param string $value */ - public function testDecodeString(string $encoded, string $value) { + public function testDecodeString(string $encoded, string $value) : void { $this->assertSame($value, $this->decoder->decodeString($encoded)); } /** * @covers ::decodeString - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Invalid string. Strings consist of two parts separated by ":". */ - public function testDecodeInvalidString() { + public function testDecodeInvalidString() : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid string. Strings consist of two parts separated by ":".'); $this->decoder->decodeString('4spam'); } /** * @covers ::decodeString - * @expectedException InvalidArgumentException - * @expectedExceptionMessage The length of the string does not match the prefix of the encoded data. */ - public function testDecodeStringWithInvalidLength() { + public function testDecodeStringWithInvalidLength() : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('The length of the string does not match the prefix of the encoded data.'); $this->decoder->decodeString('6:spam'); } - /** - * Data provider - * - * @return array[] - */ public function getDecodeListData() : array { return [ ['li1ei2ei3ee', [1, 2, 3]], @@ -133,27 +109,20 @@ public function getDecodeListData() : array { /** * @dataProvider getDecodeListData * @covers ::decodeList - * @param string $encoded - * @param array $value */ - public function testDecodeList(string $encoded, array $value) { + public function testDecodeList(string $encoded, array $value) : void { $this->assertEquals($value, $this->decoder->decodeList($encoded)); } /** * @covers ::decodeList - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Parameter is not an encoded list. */ - public function testDecodeInvalidList() { + public function testDecodeInvalidList() : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Parameter is not an encoded list.'); $this->decoder->decodeList('4:spam'); } - /** - * Data provider - * - * @return array[] - */ public function getDecodeDictionaryData() : array { return [ ['d3:foo3:bar4:spam4:eggse', ['foo' => 'bar', 'spam' => 'eggs']], @@ -163,27 +132,20 @@ public function getDecodeDictionaryData() : array { /** * @dataProvider getDecodeDictionaryData * @covers ::decodeDictionary - * @param string $encoded - * @param array $value */ - public function testDecodeDictionary(string $encoded, array $value) { + public function testDecodeDictionary(string $encoded, array $value) : void { $this->assertSame($value, $this->decoder->decodeDictionary($encoded)); } /** * @covers ::decodeDictionary - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Parameter is not an encoded dictionary. */ - public function testDecodeInvalidDictionary() { + public function testDecodeInvalidDictionary() : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Parameter is not an encoded dictionary.'); $this->decoder->decodeDictionary('4:spam'); } - /** - * Data provider - * - * @return array[] - */ public function getGenericDecodeData() : array { return [ ['i1e', 1], @@ -197,56 +159,54 @@ public function getGenericDecodeData() : array { * @dataProvider getGenericDecodeData * @covers ::__construct * @covers ::decode - * @param string $encoded - * @param int|string|array $value */ - public function testGenericDecode(string $encoded, $value) { + public function testGenericDecode(string $encoded, $value) : void { $this->assertEquals($value, $this->decoder->decode($encoded)); } /** * @covers ::decode - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Parameter is not correctly encoded. */ - public function testGenericDecodeWithInvalidData() { + public function testGenericDecodeWithInvalidData() : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Parameter is not correctly encoded.'); $this->decoder->decode('foo'); } /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Missing or empty "announce" key. * @covers ::decodeFile */ - public function testDecodeTorrentFileStrictWithMissingAnnounce() { + public function testDecodeTorrentFileStrictWithMissingAnnounce() : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Missing or empty "announce" key.'); $this->decoder->decodeFile(__DIR__ . '/_files/testMissingAnnounce.torrent', true); } /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Missing or empty "info" key. * @covers ::decodeFile */ - public function testDecodeTorrentFileStrictWithMissingInfo() { + public function testDecodeTorrentFileStrictWithMissingInfo() : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Missing or empty "info" key.'); $this->decoder->decodeFile(__DIR__ . '/_files/testMissingInfo.torrent', true); } /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage File * @covers ::decodeFile */ - public function testDecodeNonReadableFile() { + public function testDecodeNonReadableFile() : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessageRegExp('/^File .*nonExistingFile does not exist or can not be read.$/'); $this->decoder->decodeFile(__DIR__ . '/nonExistingFile'); } /** * @covers ::decodeFile */ - public function testDecodeFileWithStrictChecksEnabled() { + public function testDecodeFileWithStrictChecksEnabled() : void { $list = $this->decoder->decodeFile(__DIR__ . '/_files/valid.torrent', true); - $this->assertInternalType('array', $list); + $this->assertIsArray($list); $this->assertArrayHasKey('announce', $list); $this->assertSame('http://trackerurl', $list['announce']); $this->assertArrayHasKey('comment', $list); @@ -254,7 +214,7 @@ public function testDecodeFileWithStrictChecksEnabled() { $this->assertArrayHasKey('creation date', $list); $this->assertEquals(1323713688, $list['creation date']); $this->assertArrayHasKey('info', $list); - $this->assertInternalType('array', $list['info']); + $this->assertIsArray($list['info']); $this->assertArrayHasKey('files', $list['info']); $this->assertSame(5, count($list['info']['files'])); $this->assertArrayHasKey('name', $list['info']); From e9b3fa67663e88a3353dd8aa6c24e3a0b6054fe2 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Mon, 2 Sep 2019 19:53:27 +0200 Subject: [PATCH 41/70] Update test case --- src/Encoder.php | 2 +- tests/EncoderTest.php | 59 ++++++++----------------------------------- 2 files changed, 12 insertions(+), 49 deletions(-) diff --git a/src/Encoder.php b/src/Encoder.php index 164effd..54ba896 100644 --- a/src/Encoder.php +++ b/src/Encoder.php @@ -56,7 +56,7 @@ public function encodeString(string $string) : string { } public function encodeList(array $list) : string { - $encodedList = array_map(function($value) { + $encodedList = array_map(function($value) : string { return $this->encode($value); }, $list); diff --git a/tests/EncoderTest.php b/tests/EncoderTest.php index db7ccfa..4ff4eb9 100644 --- a/tests/EncoderTest.php +++ b/tests/EncoderTest.php @@ -1,6 +1,7 @@ encoder = new Encoder(); } - /** - * Data provider - * - * @return array[] - */ public function getEncodeIntegerData() : array { return [ [-1, 'i-1e'], @@ -33,18 +26,11 @@ public function getEncodeIntegerData() : array { /** * @dataProvider getEncodeIntegerData * @covers ::encodeInteger - * @param int $value - * @param string $encoded */ - public function testEncodeInteger(int $value, string $encoded) { + public function testEncodeInteger(int $value, string $encoded) : void { $this->assertSame($encoded, $this->encoder->encodeInteger($value)); } - /** - * Data provider - * - * @return array[] - */ public function getEncodeStringData() : array { return [ ['spam', '4:spam'], @@ -56,18 +42,11 @@ public function getEncodeStringData() : array { /** * @dataProvider getEncodeStringData * @covers ::encodeString - * @param string $value - * @param string $encoded */ - public function testEncodeString(string $value, string $encoded) { + public function testEncodeString(string $value, string $encoded) : void { $this->assertSame($encoded, $this->encoder->encodeString($value)); } - /** - * Data provider - * - * @return array[] - */ public function getEncodeListData() : array { return [ [['spam', 1, [1]], 'l4:spami1eli1eee'], @@ -77,18 +56,11 @@ public function getEncodeListData() : array { /** * @dataProvider getEncodeListData * @covers ::encodeList - * @param array $value - * @param string $encoded */ - public function testEncodeList(array $value, string $encoded) { + public function testEncodeList(array $value, string $encoded) : void { $this->assertSame($encoded, $this->encoder->encodeList($value)); } - /** - * Data provider - * - * @return array[] - */ public function getEncodeDictionaryData() : array { return [ [['1' => 'foo', 'foo' => 'bar', 'list' => [1, 2, 3]], 'd3:foo3:bar4:listli1ei2ei3ee1:13:fooe'], @@ -100,18 +72,11 @@ public function getEncodeDictionaryData() : array { /** * @dataProvider getEncodeDictionaryData * @covers ::encodeDictionary - * @param array $value - * @param string $encoded */ - public function testEncodeDictionary(array $value, string $encoded) { + public function testEncodeDictionary(array $value, string $encoded) : void { $this->assertSame($encoded, $this->encoder->encodeDictionary($value)); } - /** - * Data provider - * - * @return array[] - */ public function getEncodeData() : array { return [ [1, 'i1e'], @@ -124,19 +89,17 @@ public function getEncodeData() : array { /** * @dataProvider getEncodeData * @covers ::encode - * @param string|int|array $value - * @param string $encoded */ - public function testEncodeUsingGenericMethod($value, string $encoded) { + public function testEncodeUsingGenericMethod($value, string $encoded) : void { $this->assertSame($encoded, $this->encoder->encode($value)); } /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Variables of type object can not be encoded. * @covers ::encode */ - public function testEncodeNonSupportedType() { + public function testEncodeNonSupportedType() : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Variables of type object can not be encoded.'); $this->encoder->encode(new stdClass()); } @@ -144,7 +107,7 @@ public function testEncodeNonSupportedType() { * @covers ::__construct * @covers ::encode */ - public function testCanEncodeEmptyArraysAsDictionaries() { + public function testCanEncodeEmptyArraysAsDictionaries() : void { $encoder = new Encoder(); $this->assertSame('le', $encoder->encode([])); From 128f83650852f550fd97a3a253cd471dafdbdafc Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 08:01:32 +0200 Subject: [PATCH 42/70] Made Torrent immutable and updated test case --- src/Torrent.php | 608 ++++++++++++++++-------------------------- tests/TorrentTest.php | 401 +++++++++++++--------------- 2 files changed, 419 insertions(+), 590 deletions(-) diff --git a/src/Torrent.php b/src/Torrent.php index 20704dc..8781cfc 100644 --- a/src/Torrent.php +++ b/src/Torrent.php @@ -7,6 +7,13 @@ use InvalidArgumentException; class Torrent { + /** + * Internal encoder + * + * @var EncoderInterface + */ + private $encoder; + /** * The exponent to use when making the pieces * @@ -19,7 +26,7 @@ class Torrent { * * @var string */ - private $announce; + private $announceUrl; /** * The list of announce URLs @@ -63,31 +70,222 @@ class Torrent { */ private $extraMeta; - /** - * Class constructor - * - * @param string $announceUrl Optional announce URL - */ - public function __construct(string $announceUrl = null) { - if ($announceUrl !== null) { - $this->setAnnounce($announceUrl); + public function __construct(string $announceUrl = null, EncoderInterface $encoder = null) { + if (null !== $announceUrl) { + $this->announceUrl = $announceUrl; + } + + if (null === $encoder) { + $encoder = new Encoder(); } + + $this->encoder = $encoder; + } + + public function withPieceLengthExp(int $pieceLengthExp) : self { + $new = clone $this; + $new->pieceLengthExp = $pieceLengthExp; + + return $new; + } + + public function getPieceLengthExp() : int { + return $this->pieceLengthExp; + } + + public function withAnnounceUrl(string $announceUrl) : self { + $new = clone $this; + $new->announceUrl = $announceUrl; + + return $new; + } + + public function getAnnounceUrl() : ?string { + return $this->announceUrl; + } + + public function withEncoder(EncoderInterface $encoder) : self { + $new = clone $this; + $new->encoder = $encoder; + + return $new; + } + + public function getEncoder() : EncoderInterface { + return $this->encoder; + } + + public function withAnnounceList(array $announceList) : self { + $new = clone $this; + $new->announceList = $announceList; + + return $new; + } + + public function getAnnounceList() : ?array { + return $this->announceList; + } + + public function withComment(string $comment) : self { + $new = clone $this; + $new->comment = $comment; + + return $new; + } + + public function getComment() : ?string { + return $this->comment; + } + + public function withCreatedBy(string $createdBy) : self { + $new = clone $this; + $new->createdBy = $createdBy; + + return $new; + } + + public function getCreatedBy() : ?string { + return $this->createdBy; + } + + public function withCreatedAt(int $createdAt) : self { + $new = clone $this; + $new->createdAt = $createdAt; + + return $new; + } + + public function getCreatedAt() : ?int { + return $this->createdAt; + } + + public function withInfo(array $info) : self { + $new = clone $this; + $new->info = $info; + + return $new; + } + + public function getInfo() : ?array { + return $this->info; + } + + public function withExtraMeta(array $extra) : self { + $new = clone $this; + $new->extraMeta = $extra; + + return $new; + } + + public function getExtraMeta() : ?array { + return $this->extraMeta; } /** - * Populate the instance of the object based on a torrent file + * Save the current torrent object to the specified filename * - * @param string $path Path to the torrent file - * @param DecoderInterface $decoder The decoder to use to decode the file - * @throws InvalidArgumentException - * @return Torrent Returns a new instance of this class + * This method will save the current object to a file. If the file specified exists it will be + * overwritten. */ - static public function createFromTorrentFile($path, DecoderInterface $decoder = null) { + public function save(string $filename) : void { + if (!is_writable($filename) && !is_writable(dirname($filename))) { + throw new InvalidArgumentException(sprintf('Could not open file "%s" for writing.', $filename)); + } + + if (null === $announceUrl = $this->getAnnounceUrl()) { + throw new RuntimeException('Announce URL is missing'); + } + + $torrent = [ + 'announce' => $announceUrl, + 'creation date' => $this->getCreatedAt() ?: time(), + 'info' => $this->getInfoPart(), + ]; + + if (null !== $announceList = $this->getAnnounceList()) { + $torrent['announce-list'] = $announceList; + } + + if (null !== $comment = $this->getComment()) { + $torrent['comment'] = $comment; + } + + if (null !== $createdBy = $this->getCreatedBy()) { + $torrent['created by'] = $createdBy; + } + + if (null !== ($extra = $this->getExtraMeta()) && is_array($extra)) { + foreach ($extra as $extraKey => $extraValue) { + if (array_key_exists($extraKey, $torrent)) { + throw new RuntimeException(sprintf('Duplicate key in extra meta info. "%s" already exists.', $extraKey)); + } + + $torrent[$extraKey] = $extraValue; + } + } + + file_put_contents($filename, $this->encoder->encodeDictionary($torrent)); + } + + public function getFileList() : array { + $info = $this->getInfoPart(); + + if (isset($info['length'])) { + return [$info['name']]; + } + + return $info['files']; + } + + public function getSize() : int { + $info = $this->getInfoPart(); + + if (isset($info['length'])) { + return $info['length']; + } + + return array_sum(array_map(function(array $file) : int { + return $file['length']; + }, $this->getFileList())); + } + + public function getName() : string { + return $this->getInfoPart()['name']; + } + + public function getHash(bool $raw = false) : string { + return sha1( + $this->encoder->encodeDictionary($this->getInfoPart()), + $raw + ); + } + + public function getEncodedHash() : string { + return urlencode($this->getHash(true)); + } + + private function getInfoPart() : array { + $info = $this->getInfo(); + + if (null === $info) { + throw new RuntimeException('The info part of the torrent is not set.'); + } + + return $info; + } + + public function isPrivate() : bool { + $info = $this->getInfoPart(); + + return (isset($info['private']) && 1 === $info['private']); + } + + static public function createFromTorrentFile(string $path, DecoderInterface $decoder = null) : self { if (!is_file($path)) { throw new InvalidArgumentException(sprintf('%s does not exist.', $path)); } - if ($decoder === null) { + if (null === $decoder) { $decoder = new Decoder(); } @@ -95,53 +293,43 @@ static public function createFromTorrentFile($path, DecoderInterface $decoder = $torrent = new static(); if (isset($decodedFile['announce'])) { - $torrent->setAnnounce($decodedFile['announce']); + $torrent = $torrent->withAnnounceUrl($decodedFile['announce']); unset($decodedFile['announce']); } if (isset($decodedFile['announce-list'])) { - $torrent->setAnnounceList($decodedFile['announce-list']); + $torrent = $torrent->withAnnounceList($decodedFile['announce-list']); unset($decodedFile['announce-list']); } if (isset($decodedFile['comment'])) { - $torrent->setComment($decodedFile['comment']); + $torrent = $torrent->withComment($decodedFile['comment']); unset($decodedFile['comment']); } if (isset($decodedFile['created by'])) { - $torrent->setCreatedBy($decodedFile['created by']); + $torrent = $torrent->withCreatedBy($decodedFile['created by']); unset($decodedFile['created by']); } if (isset($decodedFile['creation date'])) { - $torrent->setCreatedAt($decodedFile['creation date']); + $torrent = $torrent->withCreatedAt($decodedFile['creation date']); unset($decodedFile['creation date']); } if (isset($decodedFile['info'])) { - $torrent->setInfo($decodedFile['info']); + $torrent = $torrent->withInfo($decodedFile['info']); unset($decodedFile['info']); } if (count($decodedFile) > 0) { - $torrent->setExtraMeta($decodedFile); + $torrent = $torrent->withExtraMeta($decodedFile); } return $torrent; } - /** - * Build a torrent from a path - * - * Some of the code in this method is ported directly from the official btmakemetafile script - * by Bram Cohen. - * - * @param string $path Path to a directory or a single file - * @param string $announceUrl URL to the announce - * @return Torrent Returns a new instance of this class - */ - static public function createFromPath($path, $announceUrl) { + static public function createFromPath(string $path, string $announceUrl = null) : self { $torrent = new static($announceUrl); $files = []; @@ -155,16 +343,11 @@ static public function createFromPath($path, $announceUrl) { 'filesize' => filesize($absolutePath), ]; } else if (false !== $absolutePath && is_dir($absolutePath)) { - $dir = new RecursiveDirectoryIterator($absolutePath); - $iterator = new RecursiveIteratorIterator($dir); + $iterator = new RecursiveIteratorIterator( + new RecursiveDirectoryIterator($absolutePath, RecursiveDirectoryIterator::SKIP_DOTS) + ); foreach ($iterator as $entry) { - $filename = $entry->getFilename(); - - if ($filename === '.' || $filename === '..') { - continue; - } - $files[] = [ 'filename' => str_replace($absolutePath . DIRECTORY_SEPARATOR, '', (string) $entry), 'filesize' => $entry->getSize(), @@ -204,14 +387,8 @@ static public function createFromPath($path, $announceUrl) { } else { $info['name'] = basename($absolutePath); - usort($files, function($a, $b) { - if ($a['filename'] < $b['filename']) { - return -1; - } else if ($a['filename'] > $b['filename']) { - return 1; - } - - return 0; + usort($files, function(array $a, array $b) : int { + return strcmp($a['filename'], $b['filename']); }); $part = ''; @@ -258,336 +435,7 @@ static public function createFromPath($path, $announceUrl) { $info['pieces'] = $pieces; ksort($info); - $torrent->setInfo($info); - - return $torrent; - } - - /** - * Set the piece length exponent - * - * @param int $pieceLengthExp The exponent to set - * @return self Returns self for a fluent interface - */ - public function setPieceLengthExp(int $pieceLengthExp) : self { - $this->pieceLengthExp = $pieceLengthExp; - - return $this; - } - - /** - * Get the piece length exponent - * - * @return int Returns the piece length exponent used when creating a torrent instance from a - * path - */ - public function getPieceLengthExp() : int { - return $this->pieceLengthExp; - } - - /** - * Set the announce URL - * - * @param string $announceUrl The URL to set - * @return self Returns self for a fluent interface - */ - public function setAnnounce(string $announceUrl) : self { - $this->announce = $announceUrl; - - return $this; - } - - /** - * Get the announce URL - * - * @return string Returns the URL to the tracker (if set) - */ - public function getAnnounce() : ?string { - return $this->announce; - } - - /** - * Set the announce list - * - * @param array $announceList The array of URLs to set - * @return self Returns self for a fluent interface - */ - public function setAnnounceList(array $announceList) : self { - $this->announceList = $announceList; - - return $this; - } - - /** - * Get the announce list - * - * @return array Returns the URL to the tracker (if set) - */ - public function getAnnounceList() : ?array { - return $this->announceList; - } - - /** - * Set the comment - * - * @param string $comment Comment to attach to the torrent file - * @return Torrent Returns self for a fluent interface - */ - public function setComment($comment) { - $this->comment = $comment; - - return $this; - } - - /** - * Get the comment - * - * @return string Returns an optional comment - */ - public function getComment() { - return $this->comment; - } - - /** - * Set the created by property - * - * @param string $createdBy Who/what created the torrent file - * @return Torrent Returns self for a fluent interface - */ - public function setCreatedBy($createdBy) { - $this->createdBy = $createdBy; - - return $this; - } - - /** - * Get the created by property - * - * @return string Returns who created the torrent (if set) - */ - public function getCreatedBy() { - return $this->createdBy; - } - - /** - * Set the creation timestamp - * - * @param int $createdAt Unix timestamp - * @return Torrent Returns self for a fluent interface - */ - public function setCreatedAt($createdAt) { - $this->createdAt = (int) $createdAt; - - return $this; - } - - /** - * Get the creation timestamp - * - * @return int Returns a unix timestamp - */ - public function getCreatedAt() { - return $this->createdAt; - } - - /** - * Set the info part of the torrent - * - * @param array $info Array with information about the torrent file - * @return Torrent Returns self for a fluent interface - */ - public function setInfo(array $info) { - $this->info = $info; - - return $this; - } - - /** - * Get the info part - * - * @return array Returns the info part of the torrent - */ - public function getInfo() { - return $this->info; - } - - /** - * Set an array of non-standard meta info that will be encoded in this torrent - * - * @param array $extra Array with information about the torrent file - * @return Torrent Returns self for a fluent interface - */ - public function setExtraMeta(array $extra) { - $this->extraMeta = $extra; - - return $this; - } - - /** - * Get extra meta info data - * - * @return array Returns an array of any non-standard meta info on this torrent - */ - public function getExtraMeta() { - return $this->extraMeta; - } - - /** - * Save the current torrent object to the specified filename - * - * This method will save the current object to a file. If the file specified exists it will be - * overwritten. - * - * @param string $filename Path to the torrent file we want to save - * @param EncoderInterface $encoder Encoder used to encode the information - * @throws InvalidArgumentException - * @throws RuntimeException - * @return Torrent Returns self for a fluent interface - */ - public function save($filename, EncoderInterface $encoder = null) { - if (!is_writable($filename) && !is_writable(dirname($filename))) { - throw new InvalidArgumentException(sprintf('Could not open file "%s" for writing.', $filename)); - } - - $info = $this->getInfoPart(); - - if ($encoder === null) { - $encoder = new Encoder(); - } - - $createdAt = $this->getCreatedAt(); - - if (empty($createdAt)) { - $createdAt = time(); - } - - $torrent = [ - 'creation date' => $createdAt, - 'info' => $info, - ]; - - if (($announce = $this->getAnnounce()) !== null) { - $torrent['announce'] = $announce; - } - - if (($announceList = $this->getAnnounceList()) !== null) { - $torrent['announce-list'] = $announceList; - } - - if (($comment = $this->getComment()) !== null) { - $torrent['comment'] = $comment; - } - - if (($createdBy = $this->getCreatedBy()) !== null) { - $torrent['created by'] = $createdBy; - } - - if (($extra = $this->getExtraMeta()) !== null && is_array($extra)) { - foreach ($extra as $extraKey => $extraValue) { - if (array_key_exists($extraKey, $torrent)) { - throw new RuntimeException(sprintf('Duplicate key in extra meta info. "%s" already exists.', $extraKey)); - } - $torrent[$extraKey] = $extraValue; - } - } - - file_put_contents($filename, $encoder->encodeDictionary($torrent)); - - return $this; - } - - /** - * Get the files listed in the torrent - * - * @return string[] List of files - */ - public function getFileList() : array { - $info = $this->getInfoPart(); - - if (isset($info['length'])) { - return [$info['name']]; - } - - return $info['files']; - } - - /** - * Get the size of the files in the torrent - * - * @return int Returns the size of the files in the torrent in bytes - */ - public function getSize() : int { - $info = $this->getInfoPart(); - - if (isset($info['length'])) { - return $info['length']; - } - - $files = $this->getFileList(); - $size = 0; - - foreach ($files as $file) { - $size += $file['length']; - } - - return $size; - } - - /** - * Get the name that the content will be saved as - * - * @return string The name of the torrent - */ - public function getName() : string { - return $this->getInfoPart()['name']; - } - - /** - * Get the hash of the torrent file - * - * @param bool $raw Set to true to return the raw 20-byte hash - * @return string The torrent hash - */ - public function getHash(bool $raw = false) : string { - return sha1( - (new Encoder())->encodeDictionary($this->getInfoPart()), - $raw - ); - } - - /** - * Get the urlencoded raw hash of the torrent file - * - * @return string The torrent hash - */ - public function getEncodedHash() : string { - return urlencode($this->getHash(true)); - } - - /** - * Get the info part of torrent and throw exception if not set - * - * @return array - * @throws RuntimeException - */ - private function getInfoPart() : array { - $info = $this->getInfo(); - - if (null === $info) { - throw new RuntimeException('The info part of the torrent is not set.'); - } - - return $info; - } - - /** - * Check if the torrent is private or not (via the optional private flag) - * - * @return bool - */ - public function isPrivate() : bool { - $info = $this->getInfoPart(); - return (isset($info['private']) && 1 === $info['private']) ? true : false; + return $torrent->withInfo($info); } } diff --git a/tests/TorrentTest.php b/tests/TorrentTest.php index d988505..87052ef 100644 --- a/tests/TorrentTest.php +++ b/tests/TorrentTest.php @@ -2,206 +2,211 @@ namespace BitTorrent; use PHPUnit\Framework\TestCase; +use RuntimeException; +use InvalidArgumentException; /** * @coversDefaultClass BitTorrent\Torrent */ class TorrentTest extends TestCase { - /** - * @var Torrent - */ private $torrent; - /** - * Set up the torrent instance - */ - public function setUp() { + public function setUp() : void { $this->torrent = new Torrent(); } /** * @covers ::__construct - * @covers ::setAnnounce - * @covers ::getAnnounce + * @covers ::getEncoder */ - public function testConstructor() { - $announce = 'http://tracker/'; - $torrent = new Torrent($announce); - $this->assertSame($announce, $torrent->getAnnounce()); + public function testConstructor() : void { + $torrent = new Torrent('http://sometracker'); + $this->assertSame('http://sometracker', $torrent->getAnnounceUrl()); + $this->assertInstanceOf(EncoderInterface::class, $torrent->getEncoder()); } /** - * @covers ::setComment - * @covers ::getComment + * @covers ::withEncoder + * @covers ::getEncoder */ - public function testSetGetComment() { - $comment = 'This is my comment'; - $this->assertSame($this->torrent, $this->torrent->setComment($comment)); - $this->assertSame($comment, $this->torrent->getComment()); + public function testSetAndGetEncoder() : void { + $encoder = $this->createMock(EncoderInterface::class); + $torrent = (new Torrent('http://sometracker'))->withEncoder($encoder); + $this->assertInstanceOf(EncoderInterface::class, $torrent->getEncoder()); } - /** - * @covers ::setCreatedBy - * @covers ::getCreatedBy - */ - public function testSetGetCreatedBy() { - $createdBy = 'Some client name'; - $this->assertSame($this->torrent, $this->torrent->setCreatedBy($createdBy)); - $this->assertSame($createdBy, $this->torrent->getCreatedBy()); + public function getDataForSettersAndGetters() : array { + return [ + 'Announce URL' => [ + 'getter' => 'getAnnounceUrl', + 'mutator' => 'withAnnounceUrl', + 'value' => 'http://tracker', + 'initial' => null, + ], + 'Piece length exponent' => [ + 'getter' => 'getPieceLengthExp', + 'mutator' => 'withPieceLengthExp', + 'value' => 6, + 'initial' => 18, + ], + 'Comment' => [ + 'getter' => 'getComment', + 'mutator' => 'withComment', + 'value' => 'some comment', + 'initial' => null, + ], + 'Announce list' => [ + 'getter' => 'getAnnounceList', + 'mutator' => 'withAnnounceList', + 'value' => ['http://sometracker'], + 'initial' => [], + ], + 'Created by' => [ + 'getter' => 'getCreatedBy', + 'mutator' => 'withCreatedBy', + 'value' => 'Some creator', + 'initial' => 'PHP BitTorrent', + ], + 'Created at' => [ + 'getter' => 'getCreatedAt', + 'mutator' => 'withCreatedAt', + 'value' => 1567451302, + 'initial' => null, + ], + 'Info' => [ + 'getter' => 'getInfo', + 'mutator' => 'withInfo', + 'value' => ['length' => 123, 'name' => 'some name'], + 'initial' => null, + ], + 'Extra meta' => [ + 'getter' => 'getExtraMeta', + 'mutator' => 'withExtraMeta', + 'value' => ['foo' => 'bar'], + 'initial' => null, + ], + ]; } /** - * @covers ::setCreatedAt + * @dataProvider getDataForSettersAndGetters + * @covers ::withAnnounceUrl + * @covers ::withPieceLengthExp + * @covers ::withComment + * @covers ::withAnnounceList + * @covers ::withCreatedBy + * @covers ::withCreatedAt + * @covers ::withInfo + * @covers ::withExtraMeta + * + * @covers ::getAnnounceUrl + * @covers ::getPieceLengthExp + * @covers ::getComment + * @covers ::getAnnounceList + * @covers ::getCreatedBy * @covers ::getCreatedAt - */ - public function testSetGetCreationDate() { - $timestamp = time(); - $this->assertSame($this->torrent, $this->torrent->setCreatedAt($timestamp)); - $this->assertSame($timestamp, $this->torrent->getCreatedAt()); - } - - /** - * @covers ::setInfo * @covers ::getInfo + * @covers ::getExtraMeta */ - public function testSetGetInfo() { - $info = ['some' => 'data']; - $this->assertSame($this->torrent, $this->torrent->setInfo($info)); - $this->assertSame($info, $this->torrent->getInfo()); - } - - /** - * @covers ::setAnnounce - * @covers ::getAnnounce - */ - public function testSetGetAnnounce() { - $announce = 'http://tracker/'; - $this->assertSame($this->torrent, $this->torrent->setAnnounce($announce)); - $this->assertSame($announce, $this->torrent->getAnnounce()); - } - - /** - * @covers ::setAnnounceList - * @covers ::getAnnounceList - */ - public function testSetGetAnnounceList() { - $announceList = ['http://tracker1/', 'http://tracker2/']; - $this->assertSame($this->torrent, $this->torrent->setAnnounceList($announceList)); - $this->assertSame($announceList, $this->torrent->getAnnounceList()); - } - - /** - * @covers ::setPieceLengthExp - * @covers ::getPieceLengthExp - */ - public function testSetGetPieceLengthExp() { - $exp = 6; - $this->assertSame($this->torrent, $this->torrent->setPieceLengthExp($exp)); - $this->assertSame($exp, $this->torrent->getPieceLengthExp()); + public function testSettersAndGetters(string $getter, string $mutator, $value, $initial) : void { + $this->assertSame($initial, $this->torrent->$getter(), 'Incorrect initial value'); + $torrent = $this->torrent->$mutator($value); + $this->assertSame($initial, $this->torrent->$getter(), 'Incorrect value after setting'); + $this->assertSame($value, $torrent->$getter(), 'Incorrect value in mutation'); } /** - * @expectedException RuntimeException * @covers ::getName */ - public function testGetNameWithNoInfoBlockAdded() { + public function testGetNameWithNoInfoBlockAdded() : void { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('The info part of the torrent is not set.'); $this->torrent->getName(); } /** - * @expectedException RuntimeException * @covers ::getSize */ - public function testGetSizeWithNoInfoBlockAdded() { + public function testGetSizeWithNoInfoBlockAdded() : void { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('The info part of the torrent is not set.'); $this->torrent->getSize(); } /** - * @expectedException RuntimeException * @covers ::getFileList */ - public function testGetFileListWithNoInfoBlockAdded() { + public function testGetFileListWithNoInfoBlockAdded() : void { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('The info part of the torrent is not set.'); $this->torrent->getFileList(); } /** - * @covers ::setInfo + * @covers ::withInfo * @covers ::getName */ - public function testGetName() { - $name = 'Some name'; - $info = ['name' => $name]; - $this->torrent->setInfo($info); - $this->assertSame($name, $this->torrent->getName()); + public function testGetName() : void { + $this->assertSame('Some name', $this->torrent->withInfo($info = ['name' => 'Some name'])->getName()); } /** - * @covers ::setInfo + * @covers ::withInfo * @covers ::getSize */ - public function testGetSizeWhenLengthIsPresentInTheInfoBlock() { - $length = 123; - $info = ['length' => $length]; - $this->torrent->setInfo($info); - $this->assertSame($length, $this->torrent->getSize()); + public function testGetSizeWhenLengthIsPresentInTheInfoBlock() : void { + $this->assertSame(123, $this->torrent->withInfo(['length' => 123])->getSize()); } /** - * @covers ::setInfo + * @covers ::withInfo * @covers ::getFileList */ - public function testGetFileListWhenInfoBlockOnlyContainsOneFile() { - $name = 'some_filename'; - $info = ['length' => 123, 'name' => $name]; - $this->torrent->setInfo($info); - $fileList = $this->torrent->getFileList(); + public function testGetFileListWhenInfoBlockOnlyContainsOneFile() : void { + $fileList = $this->torrent->withInfo(['length' => 123, 'name' => 'some_filename'])->getFileList(); $this->assertCount(1, $fileList); - $this->assertSame($name, $fileList[0]); + $this->assertSame('some_filename', $fileList[0]); } /** - * @covers ::setInfo + * @covers ::withInfo * @covers ::getFileList */ - public function testGetFileList() { + public function testGetFileList() : void { $files = [ ['length' => 12, 'path' => ['path', 'file.php']], ['length' => 32, 'path' => ['path2', 'file2.php']], ['length' => 123, 'path' => ['file.php']], ]; - $info = ['files' => $files]; - $this->torrent->setInfo($info); - $this->assertSame($files, $this->torrent->getFileList()); + $this->assertSame($files, $this->torrent->withInfo(['files' => $files])->getFileList()); } /** - * @covers ::setInfo + * @covers ::withInfo * @covers ::getSize */ - public function testGetSizeWhenInfoBlockHasSeveralFiles() { + public function testGetSizeWhenInfoBlockHasSeveralFiles() : void { $files = [ ['length' => 12, 'path' => ['path', 'file.php']], ['length' => 32, 'path' => ['path2', 'file2.php']], ['length' => 123, 'path' => ['file.php']], ]; - $info = ['files' => $files]; - $this->torrent->setInfo($info); - $this->assertEquals(167, $this->torrent->getSize()); + $this->assertEquals(167, $this->torrent->withInfo(['files' => $files])->getSize()); } /** * @covers ::createFromTorrentFile - * @covers ::getAnnounce + * @covers ::getAnnounceUrl * @covers ::getComment * @covers ::getCreatedBy * @covers ::getCreatedAt * @covers ::getSize * @covers ::getFileList */ - public function testCreateFromTorrentFile() { + public function testCreateFromTorrentFile() : void { $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/valid.torrent'); - $this->assertSame('http://trackerurl', $torrent->getAnnounce()); + $this->assertSame('http://trackerurl', $torrent->getAnnounceUrl()); $this->assertSame('This is a comment', $torrent->getComment()); $this->assertSame('PHP BitTorrent', $torrent->getCreatedBy()); $this->assertSame(1323713688, $torrent->getCreatedAt()); @@ -211,13 +216,11 @@ public function testCreateFromTorrentFile() { /** * @covers ::createFromTorrentFile - * @covers ::getAnnounce + * @covers ::getAnnounceUrl * @covers ::getFileList */ - public function testCreateFromTorrentFileWithLists() { + public function testCreateFromTorrentFileWithLists() : void { $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_extra_files/extra.torrent'); - - // we expect an array of arrays, according to the spec $announceList = [ [ 'http://tracker/', @@ -226,7 +229,7 @@ public function testCreateFromTorrentFileWithLists() { ] ]; - $this->assertSame('http://tracker/', $torrent->getAnnounce()); + $this->assertSame('http://tracker/', $torrent->getAnnounceUrl()); $this->assertEquals($announceList, $torrent->getAnnounceList()); $this->assertSame(1, count($torrent->getFileList())); } @@ -235,9 +238,8 @@ public function testCreateFromTorrentFileWithLists() { * @covers ::createFromTorrentFile * @covers ::getExtraMeta */ - public function testCreateFromTorrentFileWithExtra() { + public function testCreateFromTorrentFileWithExtra() : void { $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_extra_files/extra.torrent'); - $webSeeds = [ 'url-list' => [ @@ -252,17 +254,17 @@ public function testCreateFromTorrentFileWithExtra() { /** * @covers ::createFromPath - * @covers ::getAnnounce + * @covers ::getAnnounceUrl * @covers ::getName * @covers ::getSize * @covers ::getFileList */ - public function testCreateFromPathWhenUsingADirectoryAsArgument() { + public function testCreateFromPathWhenUsingADirectoryAsArgument() : void { $path = __DIR__ . '/_files'; $trackerUrl = 'http://trackerurl'; $torrent = Torrent::createFromPath($path, $trackerUrl); - $this->assertSame($trackerUrl, $torrent->getAnnounce()); + $this->assertSame($trackerUrl, $torrent->getAnnounceUrl()); $this->assertSame('_files', $torrent->getName()); $this->assertEquals(902910, $torrent->getSize()); $this->assertSame(7, count($torrent->getFileList())); @@ -270,17 +272,17 @@ public function testCreateFromPathWhenUsingADirectoryAsArgument() { /** * @covers ::createFromPath - * @covers ::getAnnounce + * @covers ::getAnnounceUrl * @covers ::getName * @covers ::getSize * @covers ::getFileList */ - public function testCreateFromPathWhenUsingAFileAsArgument() { + public function testCreateFromPathWhenUsingAFileAsArgument() : void { $path = __DIR__ . '/_files/valid.torrent'; $trackerUrl = 'http://trackerurl'; $torrent = Torrent::createFromPath($path, $trackerUrl); - $this->assertSame($trackerUrl, $torrent->getAnnounce()); + $this->assertSame($trackerUrl, $torrent->getAnnounceUrl()); $this->assertSame('valid.torrent', $torrent->getName()); $this->assertSame(440, $torrent->getSize()); $this->assertSame(1, count($torrent->getFileList())); @@ -288,12 +290,12 @@ public function testCreateFromPathWhenUsingAFileAsArgument() { /** * @covers ::createFromPath - * @covers ::setComment - * @covers ::setCreatedBy - * @covers ::setAnnounceList + * @covers ::withComment + * @covers ::withCreatedBy + * @covers ::withAnnounceList * @covers ::save * @covers ::createFromTorrentFile - * @covers ::getAnnounce + * @covers ::getAnnounceUrl * @covers ::getComment * @covers ::getCreatedBy * @covers ::getName @@ -302,7 +304,7 @@ public function testCreateFromPathWhenUsingAFileAsArgument() { * @covers ::getAnnounceList * @covers ::getInfoPart */ - public function testSaveTorrent() { + public function testSaveTorrent() : void { $path = __DIR__ . '/_files'; $announce = 'http://tracker/'; $announceList = [['http://tracker2'], ['http://tracker3']]; @@ -314,16 +316,14 @@ public function testSaveTorrent() { $this->fail('Could not create file: ' . $target); } - $torrent = Torrent::createFromPath($path, $announce); - $torrent->setComment($comment) - ->setCreatedBy($createdBy) - ->setAnnounceList($announceList) - ->save($target); - - // Now load the file and make sure the values are correct + $torrent = Torrent::createFromPath($path, $announce) + ->withComment($comment) + ->withCreatedBy($createdBy) + ->withAnnounceList($announceList); + $torrent->save($target); $torrent = Torrent::createFromTorrentFile($target); - $this->assertSame($announce, $torrent->getAnnounce()); + $this->assertSame($announce, $torrent->getAnnounceUrl()); $this->assertSame($comment, $torrent->getComment()); $this->assertSame($createdBy, $torrent->getCreatedBy()); $this->assertSame('_files', $torrent->getName()); @@ -331,18 +331,17 @@ public function testSaveTorrent() { $this->assertSame(7, count($torrent->getFileList())); $this->assertSame($announceList, $torrent->getAnnounceList()); - // Remove the saved file unlink($target); } /** * @covers ::createFromPath - * @covers ::setExtraMeta + * @covers ::withExtraMeta * @covers ::save * @covers ::createFromTorrentFile * @covers ::getExtraMeta */ - public function testSaveWithExtra() { + public function testSaveWithExtra() : void { $path = __DIR__ . '/_files'; $announce = 'http://tracker/'; $target = tempnam(sys_get_temp_dir(), 'PHP\BitTorrent'); @@ -359,29 +358,22 @@ public function testSaveWithExtra() { ], ]; - $torrent = Torrent::createFromPath($path, $announce); - $torrent->setExtraMeta($extra) - ->save($target); + $torrent = Torrent::createFromPath($path, $announce)->withExtraMeta($extra); + $torrent->save($target); - // Now load the file and make sure the values are correct $torrent = Torrent::createFromTorrentFile($target); $this->assertEquals($extra, $torrent->getExtraMeta()); - // Remove the saved file unlink($target); } /** - * Try to save extra fields with keys that already exist - * - * @expectedException RuntimeException - * @expectedExceptionMessage Duplicate key in extra meta info * @covers ::createFromPath - * @covers ::setExtraMeta + * @covers ::withExtraMeta * @covers ::save */ - public function testSaveWithInvalidExtra() { + public function testSaveWithInvalidExtra() : void { $path = __DIR__ . '/_files'; $announce = 'http://tracker/'; $target = tempnam(sys_get_temp_dir(), 'PHP\BitTorrent'); @@ -392,140 +384,129 @@ public function testSaveWithInvalidExtra() { $extra = ['announce' => 'http://extratracker']; - $torrent = Torrent::createFromPath($path, $announce); - $torrent->setExtraMeta($extra) - ->save($target); + $torrent = Torrent::createFromPath($path, $announce) + ->withExtraMeta($extra); - // Remove the saved file - unlink($target); + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Duplicate key in extra meta info'); + $torrent->save($target); } /** - * Try to save when no announce has been given. The code we are testing is AFTER the code that - * checks if the file specified is writeable, so make sure the argument to save() is a file that - * is writeable. - * - * @expectedException RuntimeException - * @expectedExceptionMessage Announce URL is missing * @covers ::save */ - public function testSaveWithNoAnnounce() { - $target = tempnam(sys_get_temp_dir(), 'PHP\BitTorrent'); - $this->torrent->save($target); + public function testSaveWithNoAnnounce() : void { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Announce URL is missing'); + $this->torrent->save(tempnam(sys_get_temp_dir(), 'PHP\BitTorrent')); } /** - * @expectedException RuntimeException - * @expectedExceptionMessage The info part of the torrent is not set. - * @covers ::setAnnounce + * @covers ::withAnnounceUrl * @covers ::save * @covers ::getInfoPart */ - public function testSaveWithNoInfoBlock() { - $target = tempnam(sys_get_temp_dir(), 'PHP\BitTorrent'); - $this->torrent->setAnnounce('http://tracker') - ->save($target); + public function testSaveWithNoInfoBlock() : void { + $torrent = $this->torrent->withAnnounceUrl('http://tracker'); + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('The info part of the torrent is not set.'); + $torrent->save(tempnam(sys_get_temp_dir(), 'PHP\BitTorrent')); } /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Could not open file * @covers ::createFromPath * @covers ::save */ - public function testSaveToUnwritableFile() { - $target = uniqid() . DIRECTORY_SEPARATOR . uniqid(); - + public function testSaveToUnwritableFile() : void { $torrent = Torrent::createFromPath(__FILE__, 'http://tracker/'); - $torrent->save($target); + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Could not open file'); + $torrent->save(uniqid() . DIRECTORY_SEPARATOR . uniqid()); } /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage foobar does not exist * @covers ::createFromTorrentFile */ - public function testCreateFromTorrentFileWithUnexistingTorrentFile() { + public function testCreateFromTorrentFileWithUnexistingTorrentFile() : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('foobar does not exist'); Torrent::createFromTorrentFile('foobar'); } /** - * @expectedException InvalidArgumentException - * @expectedExceptionMessage Invalid path: foobar * @covers ::createFromPath */ - public function testCreateFromPathWithInvalidPath() { + public function testCreateFromPathWithInvalidPath() : void { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid path: foobar'); Torrent::createFromPath('foobar', 'http://trackerurl'); } /** - * @expectedException RuntimeException * @covers ::getHash */ - public function testThrowsExceptionWhenTryingToGenerateHashWithEmptyTorrentFile() { + public function testThrowsExceptionWhenTryingToGenerateHashWithEmptyTorrentFile() : void { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('The info part of the torrent is not set.'); $this->torrent->getHash(); } /** - * @expectedException RuntimeException * @covers ::getEncodedHash */ - public function testThrowsExceptionWhenTryingToGenerateEncodedHashWithEmptyTorrentFile() { + public function testThrowsExceptionWhenTryingToGenerateEncodedHashWithEmptyTorrentFile() : void { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('The info part of the torrent is not set.'); $this->torrent->getEncodedHash(); } /** * @covers ::getHash */ - public function testGetHash() { - $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/valid.torrent'); - $this->assertSame('c717bfd30211a5e36c94cabaab3b3ca0dc89f91a', $torrent->getHash()); + public function testGetHash() : void { + $this->assertSame( + 'c717bfd30211a5e36c94cabaab3b3ca0dc89f91a', + Torrent::createFromTorrentFile(__DIR__ . '/_files/valid.torrent')->getHash() + ); } /** * @covers ::getEncodedHash * @covers ::getHash */ - public function testGetEncodedHash() { - $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/valid.torrent'); - $this->assertSame('%C7%17%BF%D3%02%11%A5%E3l%94%CA%BA%AB%3B%3C%A0%DC%89%F9%1A', $torrent->getEncodedHash()); + public function testGetEncodedHash() : void { + $this->assertSame( + '%C7%17%BF%D3%02%11%A5%E3l%94%CA%BA%AB%3B%3C%A0%DC%89%F9%1A', + Torrent::createFromTorrentFile(__DIR__ . '/_files/valid.torrent')->getEncodedHash() + ); } /** * @covers ::getSize */ - public function testGetSizeWithLargeValues() { - $torrent1 = Torrent::createFromTorrentFile(__DIR__ . '/_files/large_files.torrent'); - $torrent2 = Torrent::createFromTorrentFile(__DIR__ . '/_files/large_file.img.torrent'); - - $this->assertEquals("6442450944", $torrent1->getSize()); - $this->assertEquals("5368709120", $torrent2->getSize()); + public function testGetSizeWithLargeValues() : void { + $this->assertSame(6442450944, Torrent::createFromTorrentFile(__DIR__ . '/_files/large_files.torrent')->getSize()); + $this->assertSame(5368709120, Torrent::createFromTorrentFile(__DIR__ . '/_files/large_file.img.torrent')->getSize()); } /** * @covers ::isPrivate */ - public function testIsPrivateWhenFlagDoesNotExist() { - $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/large_files.torrent'); - - $this->assertFalse($torrent->isPrivate()); + public function testIsPrivateWhenFlagDoesNotExist() : void { + $this->assertFalse(Torrent::createFromTorrentFile(__DIR__ . '/_files/large_files.torrent')->isPrivate()); } /** * @covers ::isPrivate */ - public function testIsPrivateWhenItExistsAndIs1() { - $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/file_with_private_set_to_1.torrent'); - - $this->assertTrue($torrent->isPrivate()); + public function testIsPrivateWhenItExistsAndIs1() : void { + $this->assertTrue(Torrent::createFromTorrentFile(__DIR__ . '/_files/file_with_private_set_to_1.torrent')->isPrivate()); } /** * @covers ::isPrivate */ - public function testIsPrivateWhenItExistsAndIsNot1() { - $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/file_with_private_set_to_0.torrent'); - - $this->assertFalse($torrent->isPrivate()); + public function testIsPrivateWhenItExistsAndIsNot1() : void { + $this->assertFalse(Torrent::createFromTorrentFile(__DIR__ . '/_files/file_with_private_set_to_0.torrent')->isPrivate()); } } From 68ee1b79d924b05f99bcd8516622f03418f06a2f Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 08:11:46 +0200 Subject: [PATCH 43/70] Ignore PHPUnit cache file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e613a7e..4703574 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ vendor composer.phar phpunit.xml PHP_BitTorrent-*.tgz +.phpunit.result.cache From 404a89ea73ac9d8191c47cc725ccd3867edc2d77 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 08:12:08 +0200 Subject: [PATCH 44/70] Fix missing return value --- src/Torrent.php | 4 +++- tests/TorrentTest.php | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Torrent.php b/src/Torrent.php index 8781cfc..710a7d5 100644 --- a/src/Torrent.php +++ b/src/Torrent.php @@ -187,7 +187,7 @@ public function getExtraMeta() : ?array { * This method will save the current object to a file. If the file specified exists it will be * overwritten. */ - public function save(string $filename) : void { + public function save(string $filename) : self { if (!is_writable($filename) && !is_writable(dirname($filename))) { throw new InvalidArgumentException(sprintf('Could not open file "%s" for writing.', $filename)); } @@ -225,6 +225,8 @@ public function save(string $filename) : void { } file_put_contents($filename, $this->encoder->encodeDictionary($torrent)); + + return $this; } public function getFileList() : array { diff --git a/tests/TorrentTest.php b/tests/TorrentTest.php index 87052ef..df95342 100644 --- a/tests/TorrentTest.php +++ b/tests/TorrentTest.php @@ -320,7 +320,9 @@ public function testSaveTorrent() : void { ->withComment($comment) ->withCreatedBy($createdBy) ->withAnnounceList($announceList); - $torrent->save($target); + + $this->assertSame($torrent, $torrent->save($target)); + $torrent = Torrent::createFromTorrentFile($target); $this->assertSame($announce, $torrent->getAnnounceUrl()); From fbb67efb8553f639ecb8fd69d7d85d24a43cb104 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 08:12:15 +0200 Subject: [PATCH 45/70] Bump year --- LICENSE | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/LICENSE b/LICENSE index df2fecf..d1c5f24 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,4 @@ -PHP BitTorrent - -Copyright (c) 2011-2016, Christer Edvartsen +Copyright (c) 2011-2019, Christer Edvartsen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to From db8d34835a2541e3d4afe1804a787ebbc673018c Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 08:12:27 +0200 Subject: [PATCH 46/70] Update README --- README.md | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index f55a843..a1bb6a8 100644 --- a/README.md +++ b/README.md @@ -78,10 +78,8 @@ require 'vendor/autoload.php'; use BitTorrent\Torrent; -$torrent = Torrent::createFromPath('/path/to/files', 'http://tracker/announce.php'); - -$torrent - ->setComment('Some comment') +$torrent = Torrent::createFromPath('/path/to/files', 'http://tracker/announce.php') + ->withComment('Some comment') ->save('/save/to/path/file.torrent'); ``` @@ -93,15 +91,13 @@ require 'vendor/autoload.php'; use BitTorrent\Torrent; -$torrent = Torrent::createFromTorrentFile('/path/to/file.torrent'); - -$torrent - ->setAnnounce('http://tracker/announce.php') // Override announce in original file - ->setComment('Some comment') // Override commend in original file +$torrent = Torrent::createFromTorrentFile('/path/to/file.torrent') + ->withAnnounce('http://tracker/announce.php') // Override announce in original file + ->withComment('Some comment') // Override commend in original file ->save('/save/to/path/file.torrent'); // Save to a new file ``` ## License Licensed under the MIT License. -See [LICENSE](LICENSE) file. +See [LICENSE](LICENSE) file. \ No newline at end of file From f190888169571583e73f70f1737587aa05aa31d8 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 08:21:53 +0200 Subject: [PATCH 47/70] Split up into several steps --- .github/workflows/default.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml index af41a0f..04ce0d7 100644 --- a/.github/workflows/default.yml +++ b/.github/workflows/default.yml @@ -12,8 +12,20 @@ jobs: - name: Dump PHP version run: php -v + - name: Validate composer.json + run: composer validate --strict + + - name: Lint all PHP files + run: composer run qa:lint + - name: Install Barrel API Client dependencies through Composer run: composer install --prefer-dist --no-progress --no-suggest - - name: Run CI steps - run: composer run ci \ No newline at end of file + - name: Get lines of code + run: composer run qa:phploc + + - name: Run static code analyser + run: composer run qa:phpstan + + - name: Run unit tests + run: composer run test:phpunit \ No newline at end of file From 50a8f70dc55a212a2b756e66fe63b463f7a51a47 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 10:03:54 +0200 Subject: [PATCH 48/70] Try to upload artifacts --- .github/workflows/default.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml index 04ce0d7..1d9bb4b 100644 --- a/.github/workflows/default.yml +++ b/.github/workflows/default.yml @@ -24,6 +24,11 @@ jobs: - name: Get lines of code run: composer run qa:phploc + - uses: actions/upload-artifact@master + with: + name: phploc + path: build/artifacts/phploc/phploc.xml + - name: Run static code analyser run: composer run qa:phpstan From 746224781cbe6a764d0ba3ab95e811b9aa8fae15 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 10:11:38 +0200 Subject: [PATCH 49/70] Fix error in phpdoc --- src/EncoderInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EncoderInterface.php b/src/EncoderInterface.php index 9905604..a1b1b58 100644 --- a/src/EncoderInterface.php +++ b/src/EncoderInterface.php @@ -16,7 +16,7 @@ function encode($var) : string; /** * Encode an integer * - * @param int|string $integer The integer to encode + * @param int $integer The integer to encode * @return string Returns the encoded string */ function encodeInteger(int $integer) : string; From aa9e0fb40767e45658961aa6e0d81964332da875 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 10:12:00 +0200 Subject: [PATCH 50/70] Tweak some params --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index fec6f56..f15577e 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,7 @@ "scripts": { "clean:build": "rm -rf build", "qa:lint": "for file in `git ls-files '*php'`; do php -l $file; done", - "qa:phpstan": "vendor/bin/phpstan analyse src tests", + "qa:phpstan": "vendor/bin/phpstan analyse src tests -l 4", "qa:phploc": [ "rm -rf build/artifacts/phploc", "mkdir -p build/artifacts/phploc", @@ -54,7 +54,7 @@ "test:phpunit:coverage": [ "rm -rf build/artifacts/phpunit/coverage", "mkdir -p build/artifacts/phpunit/coverage", - "vendor/bin/phpunit --verbose --coverage-html build/artifacts/phpunit/coverage" + "vendor/bin/phpunit --verbose --coverage-text --coverage-html build/artifacts/phpunit/coverage" ], "test": [ "@test:phpunit" From f6105285af1b1653632f5e081c42829a05d575af Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 10:12:08 +0200 Subject: [PATCH 51/70] Upload more artifacts --- .github/workflows/default.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml index 1d9bb4b..4e3ec1f 100644 --- a/.github/workflows/default.yml +++ b/.github/workflows/default.yml @@ -33,4 +33,9 @@ jobs: run: composer run qa:phpstan - name: Run unit tests - run: composer run test:phpunit \ No newline at end of file + run: composer run test:phpunit:coverage + + - uses: actions/upload-artifact@master + with: + name: PHPUnit Code Coverage report + path: build/artifacts/phpunit/coverage \ No newline at end of file From 40402fef305994913aa60137564690a0390751cb Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 10:13:27 +0200 Subject: [PATCH 52/70] Use v1 instead of master --- .github/workflows/default.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml index 4e3ec1f..c65b44d 100644 --- a/.github/workflows/default.yml +++ b/.github/workflows/default.yml @@ -24,7 +24,7 @@ jobs: - name: Get lines of code run: composer run qa:phploc - - uses: actions/upload-artifact@master + - uses: actions/upload-artifact@v1 with: name: phploc path: build/artifacts/phploc/phploc.xml @@ -35,7 +35,7 @@ jobs: - name: Run unit tests run: composer run test:phpunit:coverage - - uses: actions/upload-artifact@master + - uses: actions/upload-artifact@v1 with: name: PHPUnit Code Coverage report path: build/artifacts/phpunit/coverage \ No newline at end of file From 6e49b4e0961e20190d043277e3a25056326a0162 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 10:25:11 +0200 Subject: [PATCH 53/70] Fix typo in docs, closes #21 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a1bb6a8..7ad6ad8 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ use BitTorrent\Encoder; $encoder = new Encoder(); var_dump($encoder->encodeString('Some string')); // string(14) "11:Some string" -var_dump($encoder->encodeInteger(42)); // int(42) +var_dump($encoder->encodeInteger(42)); // string(4) "i42e" var_dump($encoder->encodeList([1, 2, 3]); // string(11) "li1ei2ei3ee" var_dump($encoder->encodeDictionary(['foo' => 'bar', 'bar' => 'foo']); // string(22) "d3:foo3:bar3:bar3:fooe" ``` From b620f3458c5a42c1bc637cd51c32b87a16a5a4e6 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 10:42:39 +0200 Subject: [PATCH 54/70] Fix README and package name --- README.md | 32 ++++++++------------------------ composer.json | 2 +- composer.lock | 2 +- 3 files changed, 10 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 7ad6ad8..1b804f2 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,15 @@ # PHP BitTorrent **PHP BitTorrent** is a set of components that can be used to interact with torrent files (read+write) and encode/decode to/from the BitTorrent format. -[![Current Build Status](https://secure.travis-ci.org/christeredvartsen/php-bittorrent.png)](http://travis-ci.org/christeredvartsen/php-bittorrent) +[![Current Build Status](https://github.com/christeredvartsen/php-bittorrent/workflows/CI/badge.svg)](https://github.com/christeredvartsen/php-bittorrent/actions) ## Requirements -PHP BitTorrent requires PHP 7.1 or above. +PHP BitTorrent requires PHP 7.2 or above. ## Installation PHP BitTorrent can be installed using [Composer](https://getcomposer.org): -```json -{ - "require": { - "christeredvartsen/bittorrent": "^2.0" - } -} -``` + composer require christeredvartsen/php-bittorrent ^2.0 ## Using the PHP BitTorrent API ### Encode PHP variables @@ -24,9 +18,7 @@ PHP BitTorrent can be installed using [Composer](https://getcomposer.org): encodeString('Some string')); // string(14) "11:Some string" var_dump($encoder->encodeInteger(42)); // string(4) "i42e" @@ -42,9 +34,7 @@ There is also a convenience method simply called `encode` in the `BitTorrent\Enc decodeString('11:Some string')); // string(11) "Some string" var_dump($decoder->decodeInteger('i42e')); // int(42) @@ -62,9 +52,7 @@ The decoder class also has a method for decoding a torrent file (which is an enc decodeFile('/path/to/file.torrent'); ``` @@ -76,9 +64,7 @@ The `BitTorrent\Torrent` class represents a torrent file and can be used to crea withComment('Some comment') ->save('/save/to/path/file.torrent'); ``` @@ -89,9 +75,7 @@ The class can also load a torrent file: withAnnounce('http://tracker/announce.php') // Override announce in original file ->withComment('Some comment') // Override commend in original file ->save('/save/to/path/file.torrent'); // Save to a new file diff --git a/composer.json b/composer.json index f15577e..dea610e 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,5 @@ { - "name": "christeredvartsen/bittorrent", + "name": "christeredvartsen/php-bittorrent", "type": "library", "description": "A set of components that can be used to interact with torrent files (read+write) and classes that can encode/decode to/from the BitTorrent format.", "keywords": [ diff --git a/composer.lock b/composer.lock index db9643a..12f8aac 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "2ff19b93a3a486779e2d20c09131cee3", + "content-hash": "fbc640b36b52f1f798e30aeb045e4ce3", "packages": [], "packages-dev": [ { From fb4c5d8eb803f4873d8d791632ef4f179c9deff8 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 10:46:02 +0200 Subject: [PATCH 55/70] Remove extra backslash --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1b804f2..f2cf888 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ The decoder class also has a method for decoding a torrent file (which is an enc decodeFile('/path/to/file.torrent'); ``` @@ -84,4 +84,4 @@ $torrent = BitTorrent\Torrent::createFromTorrentFile('/path/to/file.torrent') ## License Licensed under the MIT License. -See [LICENSE](LICENSE) file. \ No newline at end of file +See [LICENSE](LICENSE) file. From 460a063136e0475a5c603eac71ec7a14ef3142a9 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 10:47:35 +0200 Subject: [PATCH 56/70] No longer using phpmd --- phpmd.xml | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 phpmd.xml diff --git a/phpmd.xml b/phpmd.xml deleted file mode 100644 index d3a3c84..0000000 --- a/phpmd.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - Ruleset for PHP BitTorrent - - - - - - - - - From 36fcf722f11dc2b1001c5715ba2fd193104ec047 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 3 Sep 2019 10:50:31 +0200 Subject: [PATCH 57/70] Update ChangeLog --- ChangeLog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 714f2de..f366ed9 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -7,10 +7,10 @@ __N/A__ * Use strict types * Remove support for 32 bit platforms -* Bump PHP requirement from 5.3 to 7.1 +* Bump PHP requirement from 5.3 to 7.2 * Change namespace from PHP\BitTorrent to BitTorrent -* Renamed package from `christeredvartsen/php-bittorrent` to `christeredvartsen/bittorrent` * Added method to check if the torrent is private (@stormwalkerec) +* Made `BitTorrent\Torrent` immutable Version 1.1.0 ------------- From 7e24171213b2d22c9de0d51211c1c80560baf877 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Wed, 4 Sep 2019 10:50:51 +0200 Subject: [PATCH 58/70] Add methods for dealing with file contents --- src/Decoder.php | 6 ++++- src/DecoderInterface.php | 11 ++++++++ src/Torrent.php | 55 ++++++++++++++++++++-------------------- tests/DecoderTest.php | 3 +++ tests/TorrentTest.php | 50 ++++++++++++++++++++++++++---------- 5 files changed, 83 insertions(+), 42 deletions(-) diff --git a/src/Decoder.php b/src/Decoder.php index 042ffa3..70c6ba3 100644 --- a/src/Decoder.php +++ b/src/Decoder.php @@ -15,7 +15,11 @@ public function decodeFile(string $file, bool $strict = false) : array { throw new InvalidArgumentException(sprintf('File %s does not exist or can not be read.', $file)); } - $dictionary = $this->decodeDictionary(file_get_contents($file, true)); + return $this->decodeFileContents(file_get_contents($file, true), $strict); + } + + public function decodeFileContents(string $contents, bool $strict = false) : array { + $dictionary = $this->decodeDictionary($contents); if ($strict) { if (!isset($dictionary['announce']) || !is_string($dictionary['announce']) && !empty($dictionary['announce'])) { diff --git a/src/DecoderInterface.php b/src/DecoderInterface.php index 6c4307d..a0f31b8 100644 --- a/src/DecoderInterface.php +++ b/src/DecoderInterface.php @@ -23,6 +23,17 @@ interface DecoderInterface { */ function decodeFile(string $file, bool $strict = false) : array; + /** + * Decode the contents of a file as a string + * + * @param string $contents The contents of a torrent file + * @param bool $strict If set to true this method will check for certain elements in the + * dictionary. + * @return array Returns the decoded version of the file as an array + * @throws InvalidArgumentException + */ + function decodeFileContents(string $contents, bool $strict = false) : array; + /** * Decode any bittorrent encoded string * diff --git a/src/Torrent.php b/src/Torrent.php index 710a7d5..7f49677 100644 --- a/src/Torrent.php +++ b/src/Torrent.php @@ -282,50 +282,49 @@ public function isPrivate() : bool { return (isset($info['private']) && 1 === $info['private']); } - static public function createFromTorrentFile(string $path, DecoderInterface $decoder = null) : self { - if (!is_file($path)) { - throw new InvalidArgumentException(sprintf('%s does not exist.', $path)); - } + static public function createFromString(string $contents, DecoderInterface $decoder, bool $strict = false) : self { + return static::createFromDictionary($decoder->decodeFileContents($contents, $strict)); + } - if (null === $decoder) { - $decoder = new Decoder(); - } + static public function createFromTorrentFile(string $path, DecoderInterface $decoder, bool $strict = false) : self { + return static::createFromDictionary($decoder->decodeFile($path, $strict)); + } - $decodedFile = $decoder->decodeFile($path); + static public function createFromDictionary(array $dictionary) : self { $torrent = new static(); - if (isset($decodedFile['announce'])) { - $torrent = $torrent->withAnnounceUrl($decodedFile['announce']); - unset($decodedFile['announce']); + if (isset($dictionary['announce'])) { + $torrent = $torrent->withAnnounceUrl($dictionary['announce']); + unset($dictionary['announce']); } - if (isset($decodedFile['announce-list'])) { - $torrent = $torrent->withAnnounceList($decodedFile['announce-list']); - unset($decodedFile['announce-list']); + if (isset($dictionary['announce-list'])) { + $torrent = $torrent->withAnnounceList($dictionary['announce-list']); + unset($dictionary['announce-list']); } - if (isset($decodedFile['comment'])) { - $torrent = $torrent->withComment($decodedFile['comment']); - unset($decodedFile['comment']); + if (isset($dictionary['comment'])) { + $torrent = $torrent->withComment($dictionary['comment']); + unset($dictionary['comment']); } - if (isset($decodedFile['created by'])) { - $torrent = $torrent->withCreatedBy($decodedFile['created by']); - unset($decodedFile['created by']); + if (isset($dictionary['created by'])) { + $torrent = $torrent->withCreatedBy($dictionary['created by']); + unset($dictionary['created by']); } - if (isset($decodedFile['creation date'])) { - $torrent = $torrent->withCreatedAt($decodedFile['creation date']); - unset($decodedFile['creation date']); + if (isset($dictionary['creation date'])) { + $torrent = $torrent->withCreatedAt($dictionary['creation date']); + unset($dictionary['creation date']); } - if (isset($decodedFile['info'])) { - $torrent = $torrent->withInfo($decodedFile['info']); - unset($decodedFile['info']); + if (isset($dictionary['info'])) { + $torrent = $torrent->withInfo($dictionary['info']); + unset($dictionary['info']); } - if (count($decodedFile) > 0) { - $torrent = $torrent->withExtraMeta($decodedFile); + if (count($dictionary) > 0) { + $torrent = $torrent->withExtraMeta($dictionary); } return $torrent; diff --git a/tests/DecoderTest.php b/tests/DecoderTest.php index 0e94a3b..cef49d0 100644 --- a/tests/DecoderTest.php +++ b/tests/DecoderTest.php @@ -175,6 +175,7 @@ public function testGenericDecodeWithInvalidData() : void { /** * @covers ::decodeFile + * @covers ::decodeFileContents */ public function testDecodeTorrentFileStrictWithMissingAnnounce() : void { $this->expectException(InvalidArgumentException::class); @@ -184,6 +185,7 @@ public function testDecodeTorrentFileStrictWithMissingAnnounce() : void { /** * @covers ::decodeFile + * @covers ::decodeFileContents */ public function testDecodeTorrentFileStrictWithMissingInfo() : void { $this->expectException(InvalidArgumentException::class); @@ -202,6 +204,7 @@ public function testDecodeNonReadableFile() : void { /** * @covers ::decodeFile + * @covers ::decodeFileContents */ public function testDecodeFileWithStrictChecksEnabled() : void { $list = $this->decoder->decodeFile(__DIR__ . '/_files/valid.torrent', true); diff --git a/tests/TorrentTest.php b/tests/TorrentTest.php index df95342..090d3c9 100644 --- a/tests/TorrentTest.php +++ b/tests/TorrentTest.php @@ -196,6 +196,7 @@ public function testGetSizeWhenInfoBlockHasSeveralFiles() : void { /** * @covers ::createFromTorrentFile + * @covers ::createFromDictionary * @covers ::getAnnounceUrl * @covers ::getComment * @covers ::getCreatedBy @@ -204,7 +205,28 @@ public function testGetSizeWhenInfoBlockHasSeveralFiles() : void { * @covers ::getFileList */ public function testCreateFromTorrentFile() : void { - $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/valid.torrent'); + $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_files/valid.torrent', new Decoder()); + + $this->assertSame('http://trackerurl', $torrent->getAnnounceUrl()); + $this->assertSame('This is a comment', $torrent->getComment()); + $this->assertSame('PHP BitTorrent', $torrent->getCreatedBy()); + $this->assertSame(1323713688, $torrent->getCreatedAt()); + $this->assertEquals(30243, $torrent->getSize()); + $this->assertSame(5, count($torrent->getFileList())); + } + + /** + * @covers ::createFromString + * @covers ::createFromDictionary + * @covers ::getAnnounceUrl + * @covers ::getComment + * @covers ::getCreatedBy + * @covers ::getCreatedAt + * @covers ::getSize + * @covers ::getFileList + */ + public function testCreateFromTorrentFileString() : void { + $torrent = Torrent::createFromString(file_get_contents(__DIR__ . '/_files/valid.torrent'), new Decoder()); $this->assertSame('http://trackerurl', $torrent->getAnnounceUrl()); $this->assertSame('This is a comment', $torrent->getComment()); @@ -216,11 +238,12 @@ public function testCreateFromTorrentFile() : void { /** * @covers ::createFromTorrentFile + * @covers ::createFromDictionary * @covers ::getAnnounceUrl * @covers ::getFileList */ public function testCreateFromTorrentFileWithLists() : void { - $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_extra_files/extra.torrent'); + $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_extra_files/extra.torrent', new Decoder()); $announceList = [ [ 'http://tracker/', @@ -239,7 +262,7 @@ public function testCreateFromTorrentFileWithLists() : void { * @covers ::getExtraMeta */ public function testCreateFromTorrentFileWithExtra() : void { - $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_extra_files/extra.torrent'); + $torrent = Torrent::createFromTorrentFile(__DIR__ . '/_extra_files/extra.torrent', new Decoder()); $webSeeds = [ 'url-list' => [ @@ -323,7 +346,7 @@ public function testSaveTorrent() : void { $this->assertSame($torrent, $torrent->save($target)); - $torrent = Torrent::createFromTorrentFile($target); + $torrent = Torrent::createFromTorrentFile($target, new Decoder()); $this->assertSame($announce, $torrent->getAnnounceUrl()); $this->assertSame($comment, $torrent->getComment()); @@ -363,7 +386,7 @@ public function testSaveWithExtra() : void { $torrent = Torrent::createFromPath($path, $announce)->withExtraMeta($extra); $torrent->save($target); - $torrent = Torrent::createFromTorrentFile($target); + $torrent = Torrent::createFromTorrentFile($target, new Decoder()); $this->assertEquals($extra, $torrent->getExtraMeta()); @@ -432,7 +455,7 @@ public function testSaveToUnwritableFile() : void { public function testCreateFromTorrentFileWithUnexistingTorrentFile() : void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('foobar does not exist'); - Torrent::createFromTorrentFile('foobar'); + Torrent::createFromTorrentFile('foobar', new Decoder()); } /** @@ -468,7 +491,7 @@ public function testThrowsExceptionWhenTryingToGenerateEncodedHashWithEmptyTorre public function testGetHash() : void { $this->assertSame( 'c717bfd30211a5e36c94cabaab3b3ca0dc89f91a', - Torrent::createFromTorrentFile(__DIR__ . '/_files/valid.torrent')->getHash() + Torrent::createFromTorrentFile(__DIR__ . '/_files/valid.torrent', new Decoder())->getHash() ); } @@ -479,7 +502,7 @@ public function testGetHash() : void { public function testGetEncodedHash() : void { $this->assertSame( '%C7%17%BF%D3%02%11%A5%E3l%94%CA%BA%AB%3B%3C%A0%DC%89%F9%1A', - Torrent::createFromTorrentFile(__DIR__ . '/_files/valid.torrent')->getEncodedHash() + Torrent::createFromTorrentFile(__DIR__ . '/_files/valid.torrent', new Decoder())->getEncodedHash() ); } @@ -487,28 +510,29 @@ public function testGetEncodedHash() : void { * @covers ::getSize */ public function testGetSizeWithLargeValues() : void { - $this->assertSame(6442450944, Torrent::createFromTorrentFile(__DIR__ . '/_files/large_files.torrent')->getSize()); - $this->assertSame(5368709120, Torrent::createFromTorrentFile(__DIR__ . '/_files/large_file.img.torrent')->getSize()); + $decoder = new Decoder(); + $this->assertSame(6442450944, Torrent::createFromTorrentFile(__DIR__ . '/_files/large_files.torrent', $decoder)->getSize()); + $this->assertSame(5368709120, Torrent::createFromTorrentFile(__DIR__ . '/_files/large_file.img.torrent', $decoder)->getSize()); } /** * @covers ::isPrivate */ public function testIsPrivateWhenFlagDoesNotExist() : void { - $this->assertFalse(Torrent::createFromTorrentFile(__DIR__ . '/_files/large_files.torrent')->isPrivate()); + $this->assertFalse(Torrent::createFromTorrentFile(__DIR__ . '/_files/large_files.torrent', new Decoder())->isPrivate()); } /** * @covers ::isPrivate */ public function testIsPrivateWhenItExistsAndIs1() : void { - $this->assertTrue(Torrent::createFromTorrentFile(__DIR__ . '/_files/file_with_private_set_to_1.torrent')->isPrivate()); + $this->assertTrue(Torrent::createFromTorrentFile(__DIR__ . '/_files/file_with_private_set_to_1.torrent', new Decoder())->isPrivate()); } /** * @covers ::isPrivate */ public function testIsPrivateWhenItExistsAndIsNot1() : void { - $this->assertFalse(Torrent::createFromTorrentFile(__DIR__ . '/_files/file_with_private_set_to_0.torrent')->isPrivate()); + $this->assertFalse(Torrent::createFromTorrentFile(__DIR__ . '/_files/file_with_private_set_to_0.torrent', new Decoder())->isPrivate()); } } From 1242ecd5fb5e4c113a5919d17e8da2efa389b629 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 21 Jan 2020 15:44:08 +0100 Subject: [PATCH 59/70] Update deps --- composer.json | 4 +- composer.lock | 1245 ++++++++----------------------------------------- 2 files changed, 201 insertions(+), 1048 deletions(-) diff --git a/composer.json b/composer.json index dea610e..2d789f5 100644 --- a/composer.json +++ b/composer.json @@ -18,9 +18,9 @@ "php": ">=7.2" }, "require-dev": { - "phpunit/phpunit": "^8.0", + "phpunit/phpunit": "^8.5", "phploc/phploc": "^5.0", - "phpstan/phpstan": "^0.11" + "phpstan/phpstan": "^0.12" }, "support": { "source": "https://github.com/christeredvartsen/php-bittorrent", diff --git a/composer.lock b/composer.lock index 12f8aac..cacbf9a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,831 +4,112 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "fbc640b36b52f1f798e30aeb045e4ce3", + "content-hash": "829c2bf2725619d4ec477f545139ffcc", "packages": [], "packages-dev": [ { - "name": "composer/xdebug-handler", - "version": "1.3.3", - "source": { - "type": "git", - "url": "https://github.com/composer/xdebug-handler.git", - "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/46867cbf8ca9fb8d60c506895449eb799db1184f", - "reference": "46867cbf8ca9fb8d60c506895449eb799db1184f", - "shasum": "" - }, - "require": { - "php": "^5.3.2 || ^7.0", - "psr/log": "^1.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" - }, - "type": "library", - "autoload": { - "psr-4": { - "Composer\\XdebugHandler\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "John Stevenson", - "email": "john-stevenson@blueyonder.co.uk" - } - ], - "description": "Restarts a process without xdebug.", - "keywords": [ - "Xdebug", - "performance" - ], - "time": "2019-05-27T17:52:04+00:00" - }, - { - "name": "doctrine/instantiator", - "version": "1.2.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "a2c590166b2133a4633738648b6b064edae0814a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/a2c590166b2133a4633738648b6b064edae0814a", - "reference": "a2c590166b2133a4633738648b6b064edae0814a", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "doctrine/coding-standard": "^6.0", - "ext-pdo": "*", - "ext-phar": "*", - "phpbench/phpbench": "^0.13", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-shim": "^0.11", - "phpunit/phpunit": "^7.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "time": "2019-03-17T17:37:11+00:00" - }, - { - "name": "jean85/pretty-package-versions", - "version": "1.2", - "source": { - "type": "git", - "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "75c7effcf3f77501d0e0caa75111aff4daa0dd48" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/75c7effcf3f77501d0e0caa75111aff4daa0dd48", - "reference": "75c7effcf3f77501d0e0caa75111aff4daa0dd48", - "shasum": "" - }, - "require": { - "ocramius/package-versions": "^1.2.0", - "php": "^7.0" - }, - "require-dev": { - "phpunit/phpunit": "^6.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Jean85\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Alessandro Lai", - "email": "alessandro.lai85@gmail.com" - } - ], - "description": "A wrapper for ocramius/package-versions to get pretty versions strings", - "keywords": [ - "composer", - "package", - "release", - "versions" - ], - "time": "2018-06-13T13:22:40+00:00" - }, - { - "name": "myclabs/deep-copy", - "version": "1.9.3", - "source": { - "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/007c053ae6f31bba39dfa19a7726f56e9763bbea", - "reference": "007c053ae6f31bba39dfa19a7726f56e9763bbea", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "replace": { - "myclabs/deep-copy": "self.version" - }, - "require-dev": { - "doctrine/collections": "^1.0", - "doctrine/common": "^2.6", - "phpunit/phpunit": "^7.1" - }, - "type": "library", - "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, - "files": [ - "src/DeepCopy/deep_copy.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "Create deep copies (clones) of your objects", - "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" - ], - "time": "2019-08-09T12:45:53+00:00" - }, - { - "name": "nette/bootstrap", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/nette/bootstrap.git", - "reference": "e1075af05c211915e03e0c86542f3ba5433df4a3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/bootstrap/zipball/e1075af05c211915e03e0c86542f3ba5433df4a3", - "reference": "e1075af05c211915e03e0c86542f3ba5433df4a3", - "shasum": "" - }, - "require": { - "nette/di": "^3.0", - "nette/utils": "^3.0", - "php": ">=7.1" - }, - "require-dev": { - "latte/latte": "^2.2", - "nette/application": "^3.0", - "nette/caching": "^3.0", - "nette/database": "^3.0", - "nette/forms": "^3.0", - "nette/http": "^3.0", - "nette/mail": "^3.0", - "nette/robot-loader": "^3.0", - "nette/safe-stream": "^2.2", - "nette/security": "^3.0", - "nette/tester": "^2.0", - "tracy/tracy": "^2.6" - }, - "suggest": { - "nette/robot-loader": "to use Configurator::createRobotLoader()", - "tracy/tracy": "to use Configurator::enableTracy()" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "🅱 Nette Bootstrap: the simple way to configure and bootstrap your Nette application.", - "homepage": "https://nette.org", - "keywords": [ - "bootstrapping", - "configurator", - "nette" - ], - "time": "2019-03-26T12:59:07+00:00" - }, - { - "name": "nette/di", - "version": "v3.0.1", - "source": { - "type": "git", - "url": "https://github.com/nette/di.git", - "reference": "4aff517a1c6bb5c36fa09733d4cea089f529de6d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/di/zipball/4aff517a1c6bb5c36fa09733d4cea089f529de6d", - "reference": "4aff517a1c6bb5c36fa09733d4cea089f529de6d", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "nette/neon": "^3.0", - "nette/php-generator": "^3.2.2", - "nette/robot-loader": "^3.2", - "nette/schema": "^1.0", - "nette/utils": "^3.0", - "php": ">=7.1" - }, - "conflict": { - "nette/bootstrap": "<3.0" - }, - "require-dev": { - "nette/tester": "^2.2", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ], - "files": [ - "src/compatibility.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "💎 Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP 7.1 features.", - "homepage": "https://nette.org", - "keywords": [ - "compiled", - "di", - "dic", - "factory", - "ioc", - "nette", - "static" - ], - "time": "2019-08-07T12:11:33+00:00" - }, - { - "name": "nette/finder", - "version": "v2.5.0", - "source": { - "type": "git", - "url": "https://github.com/nette/finder.git", - "reference": "6be1b83ea68ac558aff189d640abe242e0306fe2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/finder/zipball/6be1b83ea68ac558aff189d640abe242e0306fe2", - "reference": "6be1b83ea68ac558aff189d640abe242e0306fe2", - "shasum": "" - }, - "require": { - "nette/utils": "^2.4 || ~3.0.0", - "php": ">=7.1" - }, - "conflict": { - "nette/nette": "<2.2" - }, - "require-dev": { - "nette/tester": "^2.0", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.5-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "? Nette Finder: find files and directories with an intuitive API.", - "homepage": "https://nette.org", - "keywords": [ - "filesystem", - "glob", - "iterator", - "nette" - ], - "time": "2019-02-28T18:13:25+00:00" - }, - { - "name": "nette/neon", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/nette/neon.git", - "reference": "cbff32059cbdd8720deccf9e9eace6ee516f02eb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/neon/zipball/cbff32059cbdd8720deccf9e9eace6ee516f02eb", - "reference": "cbff32059cbdd8720deccf9e9eace6ee516f02eb", - "shasum": "" - }, - "require": { - "ext-iconv": "*", - "ext-json": "*", - "php": ">=7.0" - }, - "require-dev": { - "nette/tester": "^2.0", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "? Nette NEON: encodes and decodes NEON file format.", - "homepage": "http://ne-on.org", - "keywords": [ - "export", - "import", - "neon", - "nette", - "yaml" - ], - "time": "2019-02-05T21:30:40+00:00" - }, - { - "name": "nette/php-generator", - "version": "v3.2.3", - "source": { - "type": "git", - "url": "https://github.com/nette/php-generator.git", - "reference": "aea6e81437bb238e5f0e5b5ce06337433908e63b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/php-generator/zipball/aea6e81437bb238e5f0e5b5ce06337433908e63b", - "reference": "aea6e81437bb238e5f0e5b5ce06337433908e63b", - "shasum": "" - }, - "require": { - "nette/utils": "^2.4.2 || ~3.0.0", - "php": ">=7.1" - }, - "require-dev": { - "nette/tester": "^2.0", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 7.3 features.", - "homepage": "https://nette.org", - "keywords": [ - "code", - "nette", - "php", - "scaffolding" - ], - "time": "2019-07-05T13:01:56+00:00" - }, - { - "name": "nette/robot-loader", - "version": "v3.2.0", - "source": { - "type": "git", - "url": "https://github.com/nette/robot-loader.git", - "reference": "0712a0e39ae7956d6a94c0ab6ad41aa842544b5c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/robot-loader/zipball/0712a0e39ae7956d6a94c0ab6ad41aa842544b5c", - "reference": "0712a0e39ae7956d6a94c0ab6ad41aa842544b5c", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "nette/finder": "^2.5", - "nette/utils": "^3.0", - "php": ">=7.1" - }, - "require-dev": { - "nette/tester": "^2.0", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "? Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.", - "homepage": "https://nette.org", - "keywords": [ - "autoload", - "class", - "interface", - "nette", - "trait" - ], - "time": "2019-03-08T21:57:24+00:00" - }, - { - "name": "nette/schema", - "version": "v1.0.0", - "source": { - "type": "git", - "url": "https://github.com/nette/schema.git", - "reference": "6241d8d4da39e825dd6cb5bfbe4242912f4d7e4d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/6241d8d4da39e825dd6cb5bfbe4242912f4d7e4d", - "reference": "6241d8d4da39e825dd6cb5bfbe4242912f4d7e4d", - "shasum": "" - }, - "require": { - "nette/utils": "^3.0.1", - "php": ">=7.1" - }, - "require-dev": { - "nette/tester": "^2.2", - "tracy/tracy": "^2.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "📐 Nette Schema: validating data structures against a given Schema.", - "homepage": "https://nette.org", - "keywords": [ - "config", - "nette" - ], - "time": "2019-04-03T15:53:25+00:00" - }, - { - "name": "nette/utils", - "version": "v3.0.1", - "source": { - "type": "git", - "url": "https://github.com/nette/utils.git", - "reference": "bd961f49b211997202bda1d0fbc410905be370d4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/bd961f49b211997202bda1d0fbc410905be370d4", - "reference": "bd961f49b211997202bda1d0fbc410905be370d4", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "require-dev": { - "nette/tester": "~2.0", - "tracy/tracy": "^2.3" - }, - "suggest": { - "ext-gd": "to use Image", - "ext-iconv": "to use Strings::webalize() and toAscii()", - "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", - "ext-json": "to use Nette\\Utils\\Json", - "ext-mbstring": "to use Strings::lower() etc...", - "ext-xml": "to use Strings::length() etc. when mbstring is not available" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause", - "GPL-2.0", - "GPL-3.0" - ], - "authors": [ - { - "name": "David Grudl", - "homepage": "https://davidgrudl.com" - }, - { - "name": "Nette Community", - "homepage": "https://nette.org/contributors" - } - ], - "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", - "homepage": "https://nette.org", - "keywords": [ - "array", - "core", - "datetime", - "images", - "json", - "nette", - "paginator", - "password", - "slugify", - "string", - "unicode", - "utf-8", - "utility", - "validation" - ], - "time": "2019-03-22T01:00:30+00:00" - }, - { - "name": "nikic/php-parser", - "version": "v4.2.4", + "name": "doctrine/instantiator", + "version": "1.3.0", "source": { "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "97e59c7a16464196a8b9c77c47df68e4a39a45c4" + "url": "https://github.com/doctrine/instantiator.git", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/97e59c7a16464196a8b9c77c47df68e4a39a45c4", - "reference": "97e59c7a16464196a8b9c77c47df68e4a39a45c4", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", + "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": ">=7.0" + "php": "^7.1" }, "require-dev": { - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0" + "doctrine/coding-standard": "^6.0", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.13", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-shim": "^0.11", + "phpunit/phpunit": "^7.0" }, - "bin": [ - "bin/php-parse" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "4.2-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { "psr-4": { - "PhpParser\\": "lib/PhpParser" + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Nikita Popov" + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" } ], - "description": "A PHP parser written in PHP", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ - "parser", - "php" + "constructor", + "instantiate" ], - "time": "2019-09-01T07:51:21+00:00" + "time": "2019-10-21T16:45:58+00:00" }, { - "name": "ocramius/package-versions", - "version": "1.4.0", + "name": "myclabs/deep-copy", + "version": "1.9.5", "source": { "type": "git", - "url": "https://github.com/Ocramius/PackageVersions.git", - "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", - "reference": "a4d4b60d0e60da2487bd21a2c6ac089f85570dbb", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/b2c28789e80a97badd14145fda39b545d83ca3ef", + "reference": "b2c28789e80a97badd14145fda39b545d83ca3ef", "shasum": "" }, "require": { - "composer-plugin-api": "^1.0.0", - "php": "^7.1.0" + "php": "^7.1" }, - "require-dev": { - "composer/composer": "^1.6.3", - "doctrine/coding-standard": "^5.0.1", - "ext-zip": "*", - "infection/infection": "^0.7.1", - "phpunit/phpunit": "^7.0.0" + "replace": { + "myclabs/deep-copy": "self.version" }, - "type": "composer-plugin", - "extra": { - "class": "PackageVersions\\Installer", - "branch-alias": { - "dev-master": "2.0.x-dev" - } + "require-dev": { + "doctrine/collections": "^1.0", + "doctrine/common": "^2.6", + "phpunit/phpunit": "^7.1" }, + "type": "library", "autoload": { "psr-4": { - "PackageVersions\\": "src/PackageVersions" - } + "DeepCopy\\": "src/DeepCopy/" + }, + "files": [ + "src/DeepCopy/deep_copy.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" ], - "description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)", - "time": "2019-02-21T12:16:21+00:00" + "time": "2020-01-17T21:11:47+00:00" }, { "name": "phar-io/manifest", @@ -934,35 +215,33 @@ }, { "name": "phpdocumentor/reflection-common", - "version": "1.0.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", - "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", + "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", "shasum": "" }, "require": { - "php": ">=5.5" + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^4.6" + "phpunit/phpunit": "~6" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] + "phpDocumentor\\Reflection\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -984,31 +263,32 @@ "reflection", "static analysis" ], - "time": "2017-09-11T18:02:19+00:00" + "time": "2018-08-07T13:53:10+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.3.1", + "version": "4.3.4", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c" + "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", - "reference": "bdd9f737ebc2a01c06ea7ff4308ec6697db9b53c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/da3fd972d6bafd628114f7e7e036f45944b62e9c", + "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c", "shasum": "" }, "require": { "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0", - "phpdocumentor/type-resolver": "^0.4.0", + "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", + "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", "webmozart/assert": "^1.0" }, "require-dev": { - "doctrine/instantiator": "~1.0.5", + "doctrine/instantiator": "^1.0.5", "mockery/mockery": "^1.0", + "phpdocumentor/type-resolver": "0.4.*", "phpunit/phpunit": "^6.4" }, "type": "library", @@ -1035,41 +315,40 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2019-04-30T17:48:53+00:00" + "time": "2019-12-28T18:55:12+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "0.4.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", - "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", "shasum": "" }, "require": { - "php": "^5.5 || ^7.0", - "phpdocumentor/reflection-common": "^1.0" + "php": "^7.1", + "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" + "ext-tokenizer": "^7.1", + "mockery/mockery": "~1", + "phpunit/phpunit": "^7.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1082,7 +361,8 @@ "email": "me@mikevanriel.com" } ], - "time": "2017-07-14T14:27:02+00:00" + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "time": "2019-08-22T18:11:29+00:00" }, { "name": "phploc/phploc", @@ -1135,33 +415,33 @@ }, { "name": "phpspec/prophecy", - "version": "1.8.1", + "version": "v1.10.2", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76" + "reference": "b4400efc9d206e83138e2bb97ed7f5b14b831cd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76", - "reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/b4400efc9d206e83138e2bb97ed7f5b14b831cd9", + "reference": "b4400efc9d206e83138e2bb97ed7f5b14b831cd9", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", - "sebastian/comparator": "^1.1|^2.0|^3.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" }, "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", + "phpspec/phpspec": "^2.5 || ^3.2", "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.8.x-dev" + "dev-master": "1.10.x-dev" } }, "autoload": { @@ -1194,142 +474,59 @@ "spy", "stub" ], - "time": "2019-06-13T12:50:23+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "0.3.5", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "8c4ef2aefd9788238897b678a985e1d5c8df6db4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/8c4ef2aefd9788238897b678a985e1d5c8df6db4", - "reference": "8c4ef2aefd9788238897b678a985e1d5c8df6db4", - "shasum": "" - }, - "require": { - "php": "~7.1" - }, - "require-dev": { - "consistence/coding-standard": "^3.5", - "jakub-onderka/php-parallel-lint": "^0.9.2", - "phing/phing": "^2.16.0", - "phpstan/phpstan": "^0.10", - "phpunit/phpunit": "^6.3", - "slevomat/coding-standard": "^4.7.2", - "squizlabs/php_codesniffer": "^3.3.2", - "symfony/process": "^3.4 || ^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.3-dev" - } - }, - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "time": "2019-06-07T19:13:52+00:00" + "time": "2020-01-20T15:57:02+00:00" }, { "name": "phpstan/phpstan", - "version": "0.11.15", + "version": "0.12.7", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "1be5b3a706db16ac472a4c40ec03cf4c810b118d" + "reference": "07fa7958027fd98c567099bbcda5d6a0f2ec5197" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/1be5b3a706db16ac472a4c40ec03cf4c810b118d", - "reference": "1be5b3a706db16ac472a4c40ec03cf4c810b118d", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/07fa7958027fd98c567099bbcda5d6a0f2ec5197", + "reference": "07fa7958027fd98c567099bbcda5d6a0f2ec5197", "shasum": "" }, "require": { - "composer/xdebug-handler": "^1.3.0", - "jean85/pretty-package-versions": "^1.0.3", - "nette/bootstrap": "^2.4 || ^3.0", - "nette/di": "^2.4.7 || ^3.0", - "nette/robot-loader": "^3.0.1", - "nette/schema": "^1.0", - "nette/utils": "^2.4.5 || ^3.0", - "nikic/php-parser": "^4.2.3", - "php": "~7.1", - "phpstan/phpdoc-parser": "^0.3.5", - "symfony/console": "~3.2 || ~4.0", - "symfony/finder": "~3.2 || ~4.0" - }, - "conflict": { - "symfony/console": "3.4.16 || 4.1.5" - }, - "require-dev": { - "brianium/paratest": "^2.0 || ^3.0", - "consistence/coding-standard": "^3.5", - "dealerdirect/phpcodesniffer-composer-installer": "^0.4.4", - "ext-intl": "*", - "ext-mysqli": "*", - "ext-simplexml": "*", - "ext-soap": "*", - "ext-zip": "*", - "jakub-onderka/php-parallel-lint": "^1.0", - "localheinz/composer-normalize": "^1.1.0", - "phing/phing": "^2.16.0", - "phpstan/phpstan-deprecation-rules": "^0.11", - "phpstan/phpstan-php-parser": "^0.11", - "phpstan/phpstan-phpunit": "^0.11", - "phpstan/phpstan-strict-rules": "^0.11", - "phpunit/phpunit": "^7.5.14 || ^8.0", - "slevomat/coding-standard": "^4.7.2", - "squizlabs/php_codesniffer": "^3.3.2" + "php": "^7.1" }, "bin": [ - "bin/phpstan" + "phpstan", + "phpstan.phar" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "0.11-dev" + "dev-master": "0.12-dev" } }, "autoload": { - "psr-4": { - "PHPStan\\": [ - "src/", - "build/PHPStan" - ] - } + "files": [ + "bootstrap.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "description": "PHPStan - PHP Static Analysis Tool", - "time": "2019-08-18T20:51:53+00:00" + "time": "2020-01-20T21:59:06+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "7.0.7", + "version": "7.0.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "7743bbcfff2a907e9ee4a25be13d0f8ec5e73800" + "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7743bbcfff2a907e9ee4a25be13d0f8ec5e73800", - "reference": "7743bbcfff2a907e9ee4a25be13d0f8ec5e73800", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f1884187926fbb755a9aaf0b3836ad3165b478bf", + "reference": "f1884187926fbb755a9aaf0b3836ad3165b478bf", "shasum": "" }, "require": { @@ -1338,7 +535,7 @@ "php": "^7.2", "phpunit/php-file-iterator": "^2.0.2", "phpunit/php-text-template": "^1.2.1", - "phpunit/php-token-stream": "^3.1.0", + "phpunit/php-token-stream": "^3.1.1", "sebastian/code-unit-reverse-lookup": "^1.0.1", "sebastian/environment": "^4.2.2", "sebastian/version": "^2.0.1", @@ -1379,7 +576,7 @@ "testing", "xunit" ], - "time": "2019-07-25T05:31:54+00:00" + "time": "2019-11-20T13:55:58+00:00" }, { "name": "phpunit/php-file-iterator", @@ -1523,16 +720,16 @@ }, { "name": "phpunit/php-token-stream", - "version": "3.1.0", + "version": "3.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "e899757bb3df5ff6e95089132f32cd59aac2220a" + "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e899757bb3df5ff6e95089132f32cd59aac2220a", - "reference": "e899757bb3df5ff6e95089132f32cd59aac2220a", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/995192df77f63a59e47f025390d2d1fdf8f425ff", + "reference": "995192df77f63a59e47f025390d2d1fdf8f425ff", "shasum": "" }, "require": { @@ -1568,20 +765,20 @@ "keywords": [ "tokenizer" ], - "time": "2019-07-25T05:29:42+00:00" + "time": "2019-09-17T06:23:10+00:00" }, { "name": "phpunit/phpunit", - "version": "8.3.4", + "version": "8.5.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "e31cce0cf4499c0ccdbbb211a3280d36ab341e36" + "reference": "018b6ac3c8ab20916db85fa91bf6465acb64d1e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e31cce0cf4499c0ccdbbb211a3280d36ab341e36", - "reference": "e31cce0cf4499c0ccdbbb211a3280d36ab341e36", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/018b6ac3c8ab20916db85fa91bf6465acb64d1e0", + "reference": "018b6ac3c8ab20916db85fa91bf6465acb64d1e0", "shasum": "" }, "require": { @@ -1604,7 +801,7 @@ "sebastian/comparator": "^3.0.2", "sebastian/diff": "^3.0.2", "sebastian/environment": "^4.2.2", - "sebastian/exporter": "^3.1.0", + "sebastian/exporter": "^3.1.1", "sebastian/global-state": "^3.0.0", "sebastian/object-enumerator": "^3.0.3", "sebastian/resource-operations": "^2.0.1", @@ -1625,7 +822,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "8.3-dev" + "dev-master": "8.5-dev" } }, "autoload": { @@ -1651,7 +848,7 @@ "testing", "xunit" ], - "time": "2019-08-11T06:56:55+00:00" + "time": "2020-01-08T08:49:49+00:00" }, { "name": "psr/container", @@ -1702,53 +899,6 @@ ], "time": "2017-02-14T16:28:37+00:00" }, - { - "name": "psr/log", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", - "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Log\\": "Psr/Log/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", - "keywords": [ - "log", - "psr", - "psr-3" - ], - "time": "2018-11-20T15:27:04+00:00" - }, { "name": "sebastian/code-unit-reverse-lookup", "version": "1.0.1", @@ -1916,16 +1066,16 @@ }, { "name": "sebastian/environment", - "version": "4.2.2", + "version": "4.2.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404" + "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/f2a2c8e1c97c11ace607a7a667d73d47c19fe404", - "reference": "f2a2c8e1c97c11ace607a7a667d73d47c19fe404", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/464c90d7bdf5ad4e8a6aea15c091fec0603d4368", + "reference": "464c90d7bdf5ad4e8a6aea15c091fec0603d4368", "shasum": "" }, "require": { @@ -1965,20 +1115,20 @@ "environment", "hhvm" ], - "time": "2019-05-05T09:05:15+00:00" + "time": "2019-11-20T08:46:58+00:00" }, { "name": "sebastian/exporter", - "version": "3.1.1", + "version": "3.1.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "06a9a5947f47b3029d76118eb5c22802e5869687" + "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/06a9a5947f47b3029d76118eb5c22802e5869687", - "reference": "06a9a5947f47b3029d76118eb5c22802e5869687", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/68609e1261d215ea5b21b7987539cbfbe156ec3e", + "reference": "68609e1261d215ea5b21b7987539cbfbe156ec3e", "shasum": "" }, "require": { @@ -2032,27 +1182,31 @@ "export", "exporter" ], - "time": "2019-08-11T12:43:14+00:00" + "time": "2019-09-14T09:02:43+00:00" }, { "name": "sebastian/finder-facade", - "version": "1.2.2", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/finder-facade.git", - "reference": "4a3174709c2dc565fe5fb26fcf827f6a1fc7b09f" + "reference": "167c45d131f7fc3d159f56f191a0a22228765e16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/finder-facade/zipball/4a3174709c2dc565fe5fb26fcf827f6a1fc7b09f", - "reference": "4a3174709c2dc565fe5fb26fcf827f6a1fc7b09f", + "url": "https://api.github.com/repos/sebastianbergmann/finder-facade/zipball/167c45d131f7fc3d159f56f191a0a22228765e16", + "reference": "167c45d131f7fc3d159f56f191a0a22228765e16", "shasum": "" }, "require": { - "symfony/finder": "~2.3|~3.0|~4.0", - "theseer/fdomdocument": "~1.3" + "php": "^7.1", + "symfony/finder": "^2.3|^3.0|^4.0|^5.0", + "theseer/fdomdocument": "^1.6" }, "type": "library", + "extra": { + "branch-alias": [] + }, "autoload": { "classmap": [ "src/" @@ -2071,7 +1225,7 @@ ], "description": "FinderFacade is a convenience wrapper for Symfony's Finder component.", "homepage": "https://github.com/sebastianbergmann/finder-facade", - "time": "2017-11-18T17:31:49+00:00" + "time": "2020-01-16T08:08:45+00:00" }, { "name": "sebastian/global-state", @@ -2405,27 +1559,28 @@ }, { "name": "symfony/console", - "version": "v4.3.4", + "version": "v4.4.3", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "de63799239b3881b8a08f8481b22348f77ed7b36" + "reference": "e9ee09d087e2c88eaf6e5fc0f5c574f64d100e4f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/de63799239b3881b8a08f8481b22348f77ed7b36", - "reference": "de63799239b3881b8a08f8481b22348f77ed7b36", + "url": "https://api.github.com/repos/symfony/console/zipball/e9ee09d087e2c88eaf6e5fc0f5c574f64d100e4f", + "reference": "e9ee09d087e2c88eaf6e5fc0f5c574f64d100e4f", "shasum": "" }, "require": { "php": "^7.1.3", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php73": "^1.8", - "symfony/service-contracts": "^1.1" + "symfony/service-contracts": "^1.1|^2" }, "conflict": { "symfony/dependency-injection": "<3.4", - "symfony/event-dispatcher": "<4.3", + "symfony/event-dispatcher": "<4.3|>=5", + "symfony/lock": "<4.4", "symfony/process": "<3.3" }, "provide": { @@ -2433,12 +1588,12 @@ }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~3.4|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", + "symfony/config": "^3.4|^4.0|^5.0", + "symfony/dependency-injection": "^3.4|^4.0|^5.0", "symfony/event-dispatcher": "^4.3", - "symfony/lock": "~3.4|~4.0", - "symfony/process": "~3.4|~4.0", - "symfony/var-dumper": "^4.3" + "symfony/lock": "^4.4|^5.0", + "symfony/process": "^3.4|^4.0|^5.0", + "symfony/var-dumper": "^4.3|^5.0" }, "suggest": { "psr/log": "For using the console logger", @@ -2449,7 +1604,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.3-dev" + "dev-master": "4.4-dev" } }, "autoload": { @@ -2476,29 +1631,29 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2019-08-26T08:26:39+00:00" + "time": "2020-01-10T21:54:01+00:00" }, { "name": "symfony/finder", - "version": "v4.3.4", + "version": "v5.0.3", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "86c1c929f0a4b24812e1eb109262fc3372c8e9f2" + "reference": "4176e7cb846fe08f32518b7e0ed8462e2db8d9bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/86c1c929f0a4b24812e1eb109262fc3372c8e9f2", - "reference": "86c1c929f0a4b24812e1eb109262fc3372c8e9f2", + "url": "https://api.github.com/repos/symfony/finder/zipball/4176e7cb846fe08f32518b7e0ed8462e2db8d9bb", + "reference": "4176e7cb846fe08f32518b7e0ed8462e2db8d9bb", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": "^7.2.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.3-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -2525,20 +1680,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2019-08-14T12:26:46+00:00" + "time": "2020-01-04T14:08:26+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.12.0", + "version": "v1.13.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "550ebaac289296ce228a706d0867afc34687e3f4" + "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", - "reference": "550ebaac289296ce228a706d0867afc34687e3f4", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", + "reference": "f8f0b461be3385e56d6de3dbb5a0df24c0c275e3", "shasum": "" }, "require": { @@ -2550,7 +1705,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.12-dev" + "dev-master": "1.13-dev" } }, "autoload": { @@ -2583,20 +1738,20 @@ "polyfill", "portable" ], - "time": "2019-08-06T08:03:45+00:00" + "time": "2019-11-27T13:56:44+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.12.0", + "version": "v1.13.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17" + "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17", - "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/7b4aab9743c30be783b73de055d24a39cf4b954f", + "reference": "7b4aab9743c30be783b73de055d24a39cf4b954f", "shasum": "" }, "require": { @@ -2608,7 +1763,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.12-dev" + "dev-master": "1.13-dev" } }, "autoload": { @@ -2642,20 +1797,20 @@ "portable", "shim" ], - "time": "2019-08-06T08:03:45+00:00" + "time": "2019-11-27T14:18:11+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.12.0", + "version": "v1.13.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188" + "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/2ceb49eaccb9352bff54d22570276bb75ba4a188", - "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/4b0e2222c55a25b4541305a053013d5647d3a25f", + "reference": "4b0e2222c55a25b4541305a053013d5647d3a25f", "shasum": "" }, "require": { @@ -2664,7 +1819,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.12-dev" + "dev-master": "1.13-dev" } }, "autoload": { @@ -2700,24 +1855,24 @@ "portable", "shim" ], - "time": "2019-08-06T08:03:45+00:00" + "time": "2019-11-27T16:25:15+00:00" }, { "name": "symfony/service-contracts", - "version": "v1.1.6", + "version": "v2.0.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "ea7263d6b6d5f798b56a45a5b8d686725f2719a3" + "reference": "144c5e51266b281231e947b51223ba14acf1a749" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ea7263d6b6d5f798b56a45a5b8d686725f2719a3", - "reference": "ea7263d6b6d5f798b56a45a5b8d686725f2719a3", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/144c5e51266b281231e947b51223ba14acf1a749", + "reference": "144c5e51266b281231e947b51223ba14acf1a749", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": "^7.2.5", "psr/container": "^1.0" }, "suggest": { @@ -2726,7 +1881,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.0-dev" } }, "autoload": { @@ -2758,7 +1913,7 @@ "interoperability", "standards" ], - "time": "2019-08-20T14:44:19+00:00" + "time": "2019-11-18T17:27:11+00:00" }, { "name": "theseer/fdomdocument", @@ -2842,31 +1997,29 @@ }, { "name": "webmozart/assert", - "version": "1.5.0", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4" + "reference": "573381c0a64f155a0d9a23f4b0c797194805b925" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/88e6d84706d09a236046d686bbea96f07b3a34f4", - "reference": "88e6d84706d09a236046d686bbea96f07b3a34f4", + "url": "https://api.github.com/repos/webmozart/assert/zipball/573381c0a64f155a0d9a23f4b0c797194805b925", + "reference": "573381c0a64f155a0d9a23f4b0c797194805b925", "shasum": "" }, "require": { "php": "^5.3.3 || ^7.0", "symfony/polyfill-ctype": "^1.8" }, + "conflict": { + "vimeo/psalm": "<3.6.0" + }, "require-dev": { "phpunit/phpunit": "^4.8.36 || ^7.5.13" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3-dev" - } - }, "autoload": { "psr-4": { "Webmozart\\Assert\\": "src/" @@ -2888,7 +2041,7 @@ "check", "validate" ], - "time": "2019-08-24T08:43:50+00:00" + "time": "2019-11-24T13:36:37+00:00" } ], "aliases": [], From 31f47c4363d0c003bf2da55eb7b53bd856fc5a49 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 21 Jan 2020 17:56:41 +0100 Subject: [PATCH 60/70] Add configuration file for PHPStan --- phpstan.neon | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 phpstan.neon diff --git a/phpstan.neon b/phpstan.neon new file mode 100644 index 0000000..7ddc142 --- /dev/null +++ b/phpstan.neon @@ -0,0 +1,2 @@ +parameters: + checkMissingIterableValueType: false \ No newline at end of file From 7010046a3317961480565b53c48816c6f2d74aa1 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 21 Jan 2020 18:00:57 +0100 Subject: [PATCH 61/70] Skip test files, and use max level --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 2d789f5..2518fdd 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,7 @@ "scripts": { "clean:build": "rm -rf build", "qa:lint": "for file in `git ls-files '*php'`; do php -l $file; done", - "qa:phpstan": "vendor/bin/phpstan analyse src tests -l 4", + "qa:phpstan": "vendor/bin/phpstan analyse src -l max --no-progress", "qa:phploc": [ "rm -rf build/artifacts/phploc", "mkdir -p build/artifacts/phploc", From a1d957443bc19c040a25031ee1b2b3e253e5032d Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 21 Jan 2020 18:01:20 +0100 Subject: [PATCH 62/70] Cache dependencies --- .github/workflows/default.yml | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml index c65b44d..575a826 100644 --- a/.github/workflows/default.yml +++ b/.github/workflows/default.yml @@ -1,13 +1,10 @@ -name: CI - -on: [push] - +name: Build and test +on: push jobs: build: - runs-on: ubuntu-18.04 - + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Dump PHP version run: php -v @@ -18,7 +15,17 @@ jobs: - name: Lint all PHP files run: composer run qa:lint + - name: Cache Composer packages + id: composer-cache + uses: actions/cache@v1 + with: + path: vendor + key: ${{ runner.os }}-node-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-node- + - name: Install Barrel API Client dependencies through Composer + if: steps.composer-cache.outputs.cache-hit != 'true' run: composer install --prefer-dist --no-progress --no-suggest - name: Get lines of code From d1fe125128f49b0035c5d994090fae446b180672 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 21 Jan 2020 18:01:42 +0100 Subject: [PATCH 63/70] Fix issues uncovered by static analysis --- src/Decoder.php | 19 +++- src/DecoderInterface.php | 22 ++--- src/EncoderInterface.php | 4 +- src/Torrent.php | 202 +++++++++++++++++++++++++++++++++++++-- tests/TorrentTest.php | 2 +- 5 files changed, 221 insertions(+), 28 deletions(-) diff --git a/src/Decoder.php b/src/Decoder.php index 70c6ba3..66e507a 100644 --- a/src/Decoder.php +++ b/src/Decoder.php @@ -4,18 +4,29 @@ use InvalidArgumentException; class Decoder implements DecoderInterface { + /** + * @var EncoderInterface + */ private $encoder; + /** + * Class constructor + * + * @param EncoderInterface $encoder Optional encoder instance + */ public function __construct(EncoderInterface $encoder = null) { $this->encoder = $encoder ?? new Encoder(); } - public function decodeFile(string $file, bool $strict = false) : array { - if (!is_readable($file)) { - throw new InvalidArgumentException(sprintf('File %s does not exist or can not be read.', $file)); + public function decodeFile(string $path, bool $strict = false) : array { + if (!is_readable($path)) { + throw new InvalidArgumentException(sprintf('File %s does not exist or can not be read.', $path)); } - return $this->decodeFileContents(file_get_contents($file, true), $strict); + /** @var string */ + $contents = file_get_contents($path, true); + + return $this->decodeFileContents($contents, $strict); } public function decodeFileContents(string $contents, bool $strict = false) : array { diff --git a/src/DecoderInterface.php b/src/DecoderInterface.php index a0f31b8..16a264a 100644 --- a/src/DecoderInterface.php +++ b/src/DecoderInterface.php @@ -15,22 +15,22 @@ interface DecoderInterface { * * By default the method does not check for these elements. * - * @param string $file Path to the torrent file we want to decode + * @param string $path Path to the torrent file we want to decode * @param bool $strict If set to true this method will check for certain elements in the - * dictionary. - * @return array Returns the decoded version of the file as an array + * dictionary. * @throws InvalidArgumentException + * @return array Returns the decoded version of the file as an array */ - function decodeFile(string $file, bool $strict = false) : array; + function decodeFile(string $path, bool $strict = false) : array; /** * Decode the contents of a file as a string * * @param string $contents The contents of a torrent file * @param bool $strict If set to true this method will check for certain elements in the - * dictionary. - * @return array Returns the decoded version of the file as an array + * dictionary. * @throws InvalidArgumentException + * @return array Returns the decoded version of the file as an array */ function decodeFileContents(string $contents, bool $strict = false) : array; @@ -38,8 +38,8 @@ function decodeFileContents(string $contents, bool $strict = false) : array; * Decode any bittorrent encoded string * * @param string $string The string to decode - * @return int|string|array Returns the native PHP counterpart of the encoded string * @throws InvalidArgumentException + * @return int|string|array Returns the native PHP counterpart of the encoded string */ function decode(string $string); @@ -47,8 +47,8 @@ function decode(string $string); * Decode an encoded PHP integer * * @param string $integer The integer to decode - * @return int Returns the decoded integer * @throws InvalidArgumentException + * @return int Returns the decoded integer */ function decodeInteger(string $integer) : int; @@ -56,8 +56,8 @@ function decodeInteger(string $integer) : int; * Decode an encoded PHP string * * @param string $string The string to decode - * @return string Returns the decoded string value * @throws InvalidArgumentException + * @return string Returns the decoded string value */ function decodeString(string $string) : string; @@ -65,8 +65,8 @@ function decodeString(string $string) : string; * Decode an encoded PHP array * * @param string $list Encoded list - * @return array Returns a numerical array * @throws InvalidArgumentException + * @return array Returns a numerical array */ function decodeList(string $list) : array; @@ -74,8 +74,8 @@ function decodeList(string $list) : array; * Decode an encoded PHP associative array * * @param string $dictionary Encoded dictionary - * @return array Returns an associative array * @throws InvalidArgumentException + * @return array Returns an associative array */ function decodeDictionary(string $dictionary) : array; } diff --git a/src/EncoderInterface.php b/src/EncoderInterface.php index a1b1b58..aad86a7 100644 --- a/src/EncoderInterface.php +++ b/src/EncoderInterface.php @@ -7,9 +7,9 @@ interface EncoderInterface { /** * Encode any encodable variable * - * @param int|string|array $var The variable to encode - * @return string Returns the encoded string + * @param mixed $var The variable to encode. Supports: int, string and array * @throws InvalidArgumentException + * @return string Returns the encoded string */ function encode($var) : string; diff --git a/src/Torrent.php b/src/Torrent.php index 7f49677..bc23eb7 100644 --- a/src/Torrent.php +++ b/src/Torrent.php @@ -31,7 +31,7 @@ class Torrent { /** * The list of announce URLs * - * @var array + * @var string[] */ private $announceList = []; @@ -70,6 +70,12 @@ class Torrent { */ private $extraMeta; + /** + * Class constructor + * + * @param string $announceUrl Initial announce URL + * @param EncoderInterface $encoder Internal encoder instance + */ public function __construct(string $announceUrl = null, EncoderInterface $encoder = null) { if (null !== $announceUrl) { $this->announceUrl = $announceUrl; @@ -82,6 +88,12 @@ public function __construct(string $announceUrl = null, EncoderInterface $encode $this->encoder = $encoder; } + /** + * Set piece length exponent + * + * @param int $pieceLengthExp + * @return self + */ public function withPieceLengthExp(int $pieceLengthExp) : self { $new = clone $this; $new->pieceLengthExp = $pieceLengthExp; @@ -89,10 +101,21 @@ public function withPieceLengthExp(int $pieceLengthExp) : self { return $new; } + /** + * Get the piece length exponent + * + * @return int + */ public function getPieceLengthExp() : int { return $this->pieceLengthExp; } + /** + * Set the announce URL + * + * @param string $announceUrl + * @return self + */ public function withAnnounceUrl(string $announceUrl) : self { $new = clone $this; $new->announceUrl = $announceUrl; @@ -100,10 +123,21 @@ public function withAnnounceUrl(string $announceUrl) : self { return $new; } + /** + * Get the announce URL + * + * @return ?string + */ public function getAnnounceUrl() : ?string { return $this->announceUrl; } + /** + * Set the internal encoder + * + * @param EncoderInterface $encoder + * @return self + */ public function withEncoder(EncoderInterface $encoder) : self { $new = clone $this; $new->encoder = $encoder; @@ -111,10 +145,21 @@ public function withEncoder(EncoderInterface $encoder) : self { return $new; } + /** + * Get the encoder + * + * @return EncoderInterface + */ public function getEncoder() : EncoderInterface { return $this->encoder; } + /** + * Set announce URL list + * + * @param string[] $announceList + * @return self + */ public function withAnnounceList(array $announceList) : self { $new = clone $this; $new->announceList = $announceList; @@ -122,10 +167,21 @@ public function withAnnounceList(array $announceList) : self { return $new; } + /** + * Get the announce list + * + * @return string[] + */ public function getAnnounceList() : ?array { return $this->announceList; } + /** + * Set a comment + * + * @param string $comment + * @return self + */ public function withComment(string $comment) : self { $new = clone $this; $new->comment = $comment; @@ -133,10 +189,21 @@ public function withComment(string $comment) : self { return $new; } + /** + * Get the comment + * + * @return ?string + */ public function getComment() : ?string { return $this->comment; } + /** + * Set the created by field + * + * @param string $createdBy + * @return self + */ public function withCreatedBy(string $createdBy) : self { $new = clone $this; $new->createdBy = $createdBy; @@ -144,10 +211,21 @@ public function withCreatedBy(string $createdBy) : self { return $new; } + /** + * Get the created by string + * + * @return ?string + */ public function getCreatedBy() : ?string { return $this->createdBy; } + /** + * Set the created at field + * + * @param int $createdAt + * @return self + */ public function withCreatedAt(int $createdAt) : self { $new = clone $this; $new->createdAt = $createdAt; @@ -155,10 +233,21 @@ public function withCreatedAt(int $createdAt) : self { return $new; } + /** + * Get the created at field + * + * @return ?int + */ public function getCreatedAt() : ?int { return $this->createdAt; } + /** + * Set additional info + * + * @param array $info + * @return self + */ public function withInfo(array $info) : self { $new = clone $this; $new->info = $info; @@ -166,10 +255,21 @@ public function withInfo(array $info) : self { return $new; } + /** + * Get additional info + * + * @return ?array + */ public function getInfo() : ?array { return $this->info; } + /** + * Set extra metadata + * + * @param array $extra + * @return self + */ public function withExtraMeta(array $extra) : self { $new = clone $this; $new->extraMeta = $extra; @@ -177,6 +277,11 @@ public function withExtraMeta(array $extra) : self { return $new; } + /** + * Get extra metadata + * + * @return ?array + */ public function getExtraMeta() : ?array { return $this->extraMeta; } @@ -186,10 +291,14 @@ public function getExtraMeta() : ?array { * * This method will save the current object to a file. If the file specified exists it will be * overwritten. + * + * @param string $path The path to save the file to + * @throws RuntimeException + * @return bool Returns true on success or false on failure */ - public function save(string $filename) : self { - if (!is_writable($filename) && !is_writable(dirname($filename))) { - throw new InvalidArgumentException(sprintf('Could not open file "%s" for writing.', $filename)); + public function save(string $path) : bool { + if (!is_writable($path) && !is_writable(dirname($path))) { + throw new InvalidArgumentException(sprintf('Could not open file "%s" for writing.', $path)); } if (null === $announceUrl = $this->getAnnounceUrl()) { @@ -224,11 +333,14 @@ public function save(string $filename) : self { } } - file_put_contents($filename, $this->encoder->encodeDictionary($torrent)); - - return $this; + return false !== file_put_contents($path, $this->encoder->encodeDictionary($torrent)); } + /** + * Get file list + * + * @return array + */ public function getFileList() : array { $info = $this->getInfoPart(); @@ -239,6 +351,11 @@ public function getFileList() : array { return $info['files']; } + /** + * Get file size + * + * @return int + */ public function getSize() : int { $info = $this->getInfoPart(); @@ -246,15 +363,26 @@ public function getSize() : int { return $info['length']; } - return array_sum(array_map(function(array $file) : int { + return (int) array_sum(array_map(function(array $file) : int { return $file['length']; }, $this->getFileList())); } + /** + * Get the name from the info part + * + * @return string + */ public function getName() : string { return $this->getInfoPart()['name']; } + /** + * Get sha1 hash from the encoded info part + * + * @param bool $raw Whether or not to return the hash in raw format + * @return string + */ public function getHash(bool $raw = false) : string { return sha1( $this->encoder->encodeDictionary($this->getInfoPart()), @@ -262,10 +390,20 @@ public function getHash(bool $raw = false) : string { ); } + /** + * Get the encoded hash + * + * @return string + */ public function getEncodedHash() : string { return urlencode($this->getHash(true)); } + /** + * Get the info part of the torrent + * + * @return array + */ private function getInfoPart() : array { $info = $this->getInfo(); @@ -276,22 +414,49 @@ private function getInfoPart() : array { return $info; } + /** + * Check if the torrent is private + * + * @return bool + */ public function isPrivate() : bool { $info = $this->getInfoPart(); return (isset($info['private']) && 1 === $info['private']); } + /** + * Create torrent instance from a string + * + * @param string $contents + * @param DecoderInterface $decoder + * @param bool $strict + * @return self + */ static public function createFromString(string $contents, DecoderInterface $decoder, bool $strict = false) : self { return static::createFromDictionary($decoder->decodeFileContents($contents, $strict)); } + /** + * Create torrent instance from a torrent file + * + * @param string $path + * @param DecoderInterface $decoder + * @param bool $strict + * @return self + */ static public function createFromTorrentFile(string $path, DecoderInterface $decoder, bool $strict = false) : self { return static::createFromDictionary($decoder->decodeFile($path, $strict)); } + /** + * Create torrent instance from a dictionary + * + * @param array $dictionary + * @return self + */ static public function createFromDictionary(array $dictionary) : self { - $torrent = new static(); + $torrent = new self(); if (isset($dictionary['announce'])) { $torrent = $torrent->withAnnounceUrl($dictionary['announce']); @@ -330,8 +495,16 @@ static public function createFromDictionary(array $dictionary) : self { return $torrent; } + /** + * Create torrent instance from local path + * + * @param string $path + * @param string $announceUrl + * @throws RuntimeException + * @return self + */ static public function createFromPath(string $path, string $announceUrl = null) : self { - $torrent = new static($announceUrl); + $torrent = new self($announceUrl); $files = []; $absolutePath = realpath($path); @@ -371,7 +544,12 @@ static public function createFromPath(string $path, string $announceUrl = null) $position = 0; $fp = fopen($filePath . DIRECTORY_SEPARATOR . $files[0]['filename'], 'rb'); + if (false === $fp) { + throw new RuntimeException('Failed to open file'); + } + while ($position < $info['length']) { + /** @var string */ $part = fread($fp, min($info['piece length'], $info['length'] - $position)); $pieces[] = sha1($part, true); @@ -410,6 +588,10 @@ static public function createFromPath(string $path, string $announceUrl = null) $position = 0; $fp = fopen($absolutePath . DIRECTORY_SEPARATOR . $filename, 'rb'); + if (false === $fp) { + throw new RuntimeException('Failed to open file'); + } + while ($position < $filesize) { $bytes = min(($filesize - $position), ($info['piece length'] - $done)); $part .= fread($fp, $bytes); diff --git a/tests/TorrentTest.php b/tests/TorrentTest.php index 090d3c9..f9e68ab 100644 --- a/tests/TorrentTest.php +++ b/tests/TorrentTest.php @@ -344,7 +344,7 @@ public function testSaveTorrent() : void { ->withCreatedBy($createdBy) ->withAnnounceList($announceList); - $this->assertSame($torrent, $torrent->save($target)); + $this->assertTrue($torrent->save($target)); $torrent = Torrent::createFromTorrentFile($target, new Decoder()); From dfe617fb6bedc821dec916c2d72bda180945fdd3 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 21 Jan 2020 18:13:14 +0100 Subject: [PATCH 64/70] Fix syntax error --- .github/workflows/default.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml index 575a826..90248d1 100644 --- a/.github/workflows/default.yml +++ b/.github/workflows/default.yml @@ -16,13 +16,13 @@ jobs: run: composer run qa:lint - name: Cache Composer packages - id: composer-cache - uses: actions/cache@v1 - with: - path: vendor - key: ${{ runner.os }}-node-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-node- + id: composer-cache + uses: actions/cache@v1 + with: + path: vendor + key: ${{ runner.os }}-node-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-node- - name: Install Barrel API Client dependencies through Composer if: steps.composer-cache.outputs.cache-hit != 'true' From d0f341152b11897f2be470084e14b036a3090a40 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 21 Jan 2020 19:01:20 +0100 Subject: [PATCH 65/70] Add filename to the error messages --- src/Torrent.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Torrent.php b/src/Torrent.php index bc23eb7..713f55e 100644 --- a/src/Torrent.php +++ b/src/Torrent.php @@ -542,10 +542,10 @@ static public function createFromPath(string $path, string $announceUrl = null) $info['name'] = $files[0]['filename']; $info['length'] = $files[0]['filesize']; $position = 0; - $fp = fopen($filePath . DIRECTORY_SEPARATOR . $files[0]['filename'], 'rb'); + $fp = fopen($p = $filePath . DIRECTORY_SEPARATOR . $files[0]['filename'], 'rb'); if (false === $fp) { - throw new RuntimeException('Failed to open file'); + throw new RuntimeException(sprintf('Failed to open file: %s', $p)); } while ($position < $info['length']) { @@ -586,10 +586,10 @@ static public function createFromPath(string $path, string $announceUrl = null) ]; $position = 0; - $fp = fopen($absolutePath . DIRECTORY_SEPARATOR . $filename, 'rb'); + $fp = fopen($p = $absolutePath . DIRECTORY_SEPARATOR . $filename, 'rb'); if (false === $fp) { - throw new RuntimeException('Failed to open file'); + throw new RuntimeException(sprintf('Failed to open file: %s', $p)); } while ($position < $filesize) { From 491d889234bcc1f5857b81280f007b268a13700d Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 21 Jan 2020 19:02:44 +0100 Subject: [PATCH 66/70] Bump year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index d1c5f24..eb65e68 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011-2019, Christer Edvartsen +Copyright (c) 2011-2020, Christer Edvartsen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to From 4bcc536c836ae618884dfb5c96230b892b58e694 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 21 Jan 2020 20:07:38 +0100 Subject: [PATCH 67/70] Fix badge URL, and added link to BitTorrent spec --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f2cf888..cfab7ba 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # PHP BitTorrent -**PHP BitTorrent** is a set of components that can be used to interact with torrent files (read+write) and encode/decode to/from the BitTorrent format. +**PHP BitTorrent** is a set of components that can be used to interact with torrent files (read+write) and encode/decode to/from the [BitTorrent format](https://wiki.theory.org/index.php/BitTorrentSpecification). -[![Current Build Status](https://github.com/christeredvartsen/php-bittorrent/workflows/CI/badge.svg)](https://github.com/christeredvartsen/php-bittorrent/actions) +[![Current Build Status](https://github.com/christeredvartsen/php-bittorrent/workflows/Build%20and%20test/badge.svg)](https://github.com/christeredvartsen/php-bittorrent/actions) ## Requirements PHP BitTorrent requires PHP 7.2 or above. From 95a7b2ab67c383ebfa9746b023ca5ba8e470b099 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 21 Jan 2020 20:08:58 +0100 Subject: [PATCH 68/70] Fix outdated example --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cfab7ba..0d786f0 100644 --- a/README.md +++ b/README.md @@ -77,8 +77,9 @@ require 'vendor/autoload.php'; $torrent = BitTorrent\Torrent::createFromTorrentFile('/path/to/file.torrent') ->withAnnounce('http://tracker/announce.php') // Override announce in original file - ->withComment('Some comment') // Override commend in original file - ->save('/save/to/path/file.torrent'); // Save to a new file + ->withComment('Some comment'); // Override commend in original file + +$torrent->save('/save/to/path/file.torrent'); // Save to a new file ``` ## License From 9d7cbdc481cfd6df62430f9ad2d98b5f8092e9f7 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 21 Jan 2020 20:10:14 +0100 Subject: [PATCH 69/70] Fix another example --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0d786f0..e412859 100644 --- a/README.md +++ b/README.md @@ -65,8 +65,9 @@ The `BitTorrent\Torrent` class represents a torrent file and can be used to crea require 'vendor/autoload.php'; $torrent = BitTorrent\Torrent::createFromPath('/path/to/files', 'http://tracker/announce.php') - ->withComment('Some comment') - ->save('/save/to/path/file.torrent'); + ->withComment('Some comment'); + +$torrent->save('/save/to/path/file.torrent'); ``` The class can also load a torrent file: From 94d939f62e1b1d4b16fc35964b854b00c8f01864 Mon Sep 17 00:00:00 2001 From: Christer Edvartsen Date: Tue, 21 Jan 2020 20:11:46 +0100 Subject: [PATCH 70/70] Set release date --- ChangeLog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index f366ed9..17e3907 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -3,7 +3,7 @@ Changelog for PHP BitTorrent Version 2.0.0 ------------- -__N/A__ +__2020-01-21__ * Use strict types * Remove support for 32 bit platforms