Skip to content

Commit

Permalink
Merge branch 'master' of github.com:mpociot/slack-client
Browse files Browse the repository at this point in the history
  • Loading branch information
mpociot committed Feb 21, 2017
2 parents 8c71aab + 8e4e56a commit 16a5ffe
Show file tree
Hide file tree
Showing 3 changed files with 258 additions and 6 deletions.
53 changes: 47 additions & 6 deletions src/ApiClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -370,17 +370,41 @@ public function postMessage(Message $message)
return $this->apiCall('chat.postMessage', $options);
}

/**
* Uploads a file.
*
* @param \Slack\File $file The file to upload.
* @param array Array of channel IDs or names to upload the file to.
*
* @return \React\Promise\PromiseInterface
*/
public function fileUpload(File $file, array $channels)
{
$multipart = !$file->isSnippet();

$options = [
'title' => $file->getTitle(),
'content' => !$multipart ? file_get_contents($file->getPath()) : null,
'file' => $multipart ? fopen($file->getPath(), 'r') : null,
'initial_comment' => $file->getInitialComment(),
'channels' => implode(',', $channels),
];

return $this->apiCall('files.upload', $options, $multipart);
}

/**
* Sends an API request.
*
* @param string $method The API method to call.
* @param array $args An associative array of arguments to pass to the
* method call.
* @param string $method The API method to call.
* @param array $args An associative array of arguments to pass to the
* method call.
* @param bool $multipart Whether to send as a multipart request. Default to false
* @param bool $callDeferred Wether to call the API asynchronous or not.
*
* @return \React\Promise\PromiseInterface A promise for an API response.
*/
public function apiCall($method, array $args = [], $callDeferred = true)
public function apiCall($method, array $args = [], $multipart = false, $callDeferred = true)
{
// create the request url
$requestUrl = self::BASE_URL . $method;
Expand All @@ -389,8 +413,11 @@ public function apiCall($method, array $args = [], $callDeferred = true)
$args['token'] = $this->token;

// send a post request with all arguments
$requestType = $multipart ? 'multipart' : 'form_params';
$requestData = $multipart ? $this->convertToMultipartArray($args) : $args;

$promise = $this->httpClient->postAsync($requestUrl, [
'form_params' => $args,
$requestType => $requestData,
]);

// Add requests to the event loop to be handled at a later date.
Expand Down Expand Up @@ -423,4 +450,18 @@ public function apiCall($method, array $args = [], $callDeferred = true)

return $deferred->promise();
}
}

private function convertToMultipartArray(array $options)
{
$convertedOptions = [];

foreach ($options as $key => $value) {
$convertedOptions[] = [
'name' => $key,
'contents' => $value,
];
}

return $convertedOptions;
}
}
145 changes: 145 additions & 0 deletions src/File.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php
namespace Slack;

/**
* Contains the information about a file to be uploaded.
*/
class File
{
/**
* @var string Path to the file.
*/
protected $path;

/**
* @var bool
*/
protected $snippet;

/**
* @var string The file's title.
*/
protected $title;

/**
* @var string Filename of file.
*/
protected $filename;

/**
* @var string Initial comment to add to file.
*/
protected $initialComment;

/**
* @var string A file type identifier.
*/
protected $filetype;

/**
* @return string
*/
public function getPath()
{
return $this->path;
}

/**
* @param string $path
* @return File
*/
public function setPath($path)
{
$this->path = $path;
return $this;
}

/**
* @return bool
*/
public function isSnippet()
{
return $this->snippet;
}

/**
* @param bool $snippet
*/
public function treatAsSnippet($snippet)
{
$this->snippet = $snippet;
return $this;
}

/**
* @return string
*/
public function getTitle()
{
return $this->title;
}

/**
* @param string $title
* @return File
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}

/**
* @return string
*/
public function getFilename()
{
return $this->filename;
}

/**
* @param string $filename
* @return File
*/
public function setFilename($filename)
{
$this->filename = $filename;
return $this;
}

/**
* @return string
*/
public function getInitialComment()
{
return $this->initialComment;
}

/**
* @param string $initialComment
* @return File
*/
public function setInitialComment($initialComment)
{
$this->initialComment = $initialComment;
return $this;
}

/**
* @return string
*/
public function getFiletype()
{
return $this->filetype;
}

/**
* @param string $filetype
* @return File
*/
public function setFiletype($filetype)
{
$this->filetype = $filetype;
return $this;
}
}
66 changes: 66 additions & 0 deletions tests/ApiClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
namespace Slack\Tests;

use Slack\ApiClient;
use Slack\Channel;
use Slack\File;
use Slack\Payload;
use Slack\Team;
use Slack\User;
Expand Down Expand Up @@ -93,6 +95,36 @@ public function testGetUserByName()
$this->watchPromise($users);
}

public function testFileUpload()
{
$fileId = $this->faker->uuid;
$channelId = $this->faker->uuid;

$this->mockResponse(200, [], [
'ok' => true,
'file' => [
'id' => $fileId,
'title' => $this->faker->title,
],
]);

$file = new File();
$file->setPath($this->faker->image(sys_get_temp_dir()))
->setTitle($this->faker->title)
->setInitialComment($this->faker->sentence())
->setFilename($this->faker->name)
->setFiletype('png');

$response = $this->client->fileUpload($file, [$channelId])
->then(function (Payload $response) use ($fileId) {
$this->assertEquals($fileId, $response['file']['id']);

$this->assertLastRequestUrl(ApiClient::BASE_URL.'files.upload');
});

$this->watchPromise($response);
}

public function testApiCall()
{
// add the mock subscriber to the client
Expand All @@ -111,4 +143,38 @@ public function testApiCall()

$this->watchPromise($response);
}

public function testMultipartApiCall()
{
$this->mockResponse(200, [], [
'ok' => true,
]);

$args = [
'title' => $this->faker->title,
'files' => $this->faker->sentence,
];

$multipart = true;

$response = $this->client->apiCall('files.upload', $args, $multipart)
->then(function () {
$this->assertCount(1, $this->history);

$this->assertLastRequestUrl(ApiClient::BASE_URL . 'files.upload');

/** @var \GuzzleHttp\Psr7\Request $request */
$request = current($this->history)['request'];

$contentType = $request->getHeaderLine('content-type');
$this->assertContains('multipart/form-data', $contentType);

$requestContents = $request->getBody()->getContents();
$this->assertContains('name="title"', $requestContents);
$this->assertContains('name="files"', $requestContents);
$this->assertContains('name="token"', $requestContents);
});

$this->watchPromise($response);
}
}

0 comments on commit 16a5ffe

Please sign in to comment.