diff --git a/README.md b/README.md index 897e9d8..7ac988a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Max Bot API Client library for PHP +# Max Messenger Bot API Client library for PHP [![Actions status](https://github.com/BushlanovDev/max-bot-api-client-php/actions/workflows/ci.yml/badge.svg?style=flat-square)](https://github.com/BushlanovDev/max-bot-api-client-php/actions) [![Coverage](https://raw.githubusercontent.com/BushlanovDev/max-bot-api-client-php/refs/heads/master/.github/badge-coverage.svg?v=2)](https://github.com/BushlanovDev/max-bot-api-client-php/actions) diff --git a/docs/README.md b/docs/README.md index f025196..6077c77 100644 --- a/docs/README.md +++ b/docs/README.md @@ -332,7 +332,8 @@ $updateList = $api->getUpdates( ```php $uploadEndpoint = $api->getUploadUrl(UploadType::Video); -// Далее вы можете загрузить файл по полученному URL самостоятельно или воспользоваться методом Client::upload() +// Далее вы можете загрузить файл по полученному URL самостоятельно +// или воспользоваться методами Client::multipartUpload(), Client::resumableUpload(), Api::uploadFile() ``` ### Загрузка файла diff --git a/src/Api.php b/src/Api.php index 8d7e242..39f1358 100644 --- a/src/Api.php +++ b/src/Api.php @@ -446,6 +446,8 @@ class Api } /** + * Uploads a file to the specified URL. + * * @param string $uploadUrl The target URL for the upload. * @param resource $fileHandle A stream resource pointing to the file. * @param string $fileName The desired file name for the upload. diff --git a/src/Client.php b/src/Client.php index d7edadd..5d48fa7 100644 --- a/src/Client.php +++ b/src/Client.php @@ -181,7 +181,9 @@ final readonly class Client implements ClientApiInterface while (!feof($fileResource)) { $chunk = fread($fileResource, $chunkSize); if ($chunk === false) { + // @codeCoverageIgnoreStart throw new RuntimeException('Failed to read chunk from file stream.'); + // @codeCoverageIgnoreEnd } $chunkLength = strlen($chunk); diff --git a/tests/ClientTest.php b/tests/ClientTest.php index 00b901d..323179b 100644 --- a/tests/ClientTest.php +++ b/tests/ClientTest.php @@ -451,4 +451,89 @@ final class ClientTest extends TestCase $this->client->resumableUpload('http://a.b', $fileResource, 'file.txt', 9); fclose($fileResource); } + + #[Test] + public function resumableUploadSuccessfullyUploadsSingleChunk(): void + { + $fileContents = 'test-data'; + $fileResource = fopen('php://memory', 'w+'); + fwrite($fileResource, $fileContents); + rewind($fileResource); + + $uploadUrl = 'http://a.b'; + $fileName = 'file.txt'; + $fileSize = strlen($fileContents); + + $this->requestFactoryMock->method('createRequest')->willReturn($this->requestMock); + $this->requestMock->method('withBody')->willReturnSelf(); + $this->requestMock->method('withHeader')->willReturnSelf(); + + $this->httpClientMock + ->expects($this->once()) + ->method('sendRequest') + ->with($this->requestMock) + ->willReturn($this->responseMock); + + $this->responseMock->method('getStatusCode')->willReturn(200); + $this->streamMock->method('__toString')->willReturn('1'); + + $result = $this->client->resumableUpload($uploadUrl, $fileResource, $fileName, $fileSize); + + $this->assertSame('1', $result); + fclose($fileResource); + } + + #[Test] + public function resumableUploadSuccessfullyUploadsMultipleChunks(): void + { + $fileContents = str_repeat('A', 3 * 1024 * 1024); // 3 MB + $fileResource = fopen('php://memory', 'w+'); + fwrite($fileResource, $fileContents); + rewind($fileResource); + + $uploadUrl = 'http://a.b'; + $fileName = 'bigfile.bin'; + $fileSize = strlen($fileContents); + + $this->requestFactoryMock->method('createRequest')->willReturn($this->requestMock); + $this->requestMock->method('withBody')->willReturnSelf(); + $this->requestMock->method('withHeader')->willReturnSelf(); + + $this->httpClientMock + ->expects($this->exactly(3)) + ->method('sendRequest') + ->willReturnOnConsecutiveCalls( + $this->responseMock, + $this->responseMock, + $this->responseMock, + ); + + $this->responseMock->method('getStatusCode')->willReturn(200); + $this->streamMock + ->method('__toString') + ->willReturnOnConsecutiveCalls('', '', '1'); + + $result = $this->client->resumableUpload($uploadUrl, $fileResource, $fileName, $fileSize, 1024 * 1024); + + $this->assertSame('1', $result); + fclose($fileResource); + } + + #[Test] + public function resumableUploadStopsOnEmptyChunk(): void + { + $fileResource = fopen('php://memory', 'w+'); + rewind($fileResource); + + $uploadUrl = 'http://a.b'; + $fileName = 'empty.txt'; + + $this->requestFactoryMock->expects($this->never())->method('createRequest'); + $this->httpClientMock->expects($this->never())->method('sendRequest'); + + $result = $this->client->resumableUpload($uploadUrl, $fileResource, $fileName, 100); + + $this->assertSame('', $result); + fclose($fileResource); + } }