Skip to content
This repository was archived by the owner on Jan 21, 2020. It is now read-only.

Commit 7156687

Browse files
committed
Merge branch 'hotfix/48-status-update-via-post'
Close #53 Fixes #48 Fixes #49
2 parents ca26c83 + 86dfeb6 commit 7156687

File tree

4 files changed

+94
-24
lines changed

4 files changed

+94
-24
lines changed

CHANGELOG.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,20 @@ All notable changes to this project will be documented in this file, in reverse
2222

2323
### Fixed
2424

25-
- [#51](https://github.com/zendframework/ZendService_Twitter/pull/51) fixes
26-
submission of direct messages to the Twitter API. Payloads for DMs have been
27-
broken since the 3.0.0 release.
25+
- [#53](https://github.com/zendframework/ZendService_Twitter/pull/53) fixes
26+
issues in the majority of POST endpoints. Due to a mis-read of the Twitter API
27+
documentation, we were sending JSON payloads, when only a small subset of such
28+
endpoints actually can accept JSON. In particular, `statuses/update` was
29+
affected. The patch in this releases fixes all such endpoints.
2830

2931
- [#52](https://github.com/zendframework/ZendService_Twitter/pull/52) fixes
3032
the `search/tweets` logic concerning geocode parameter validation, ensuring it
3133
no longer raises an exception for a valid geocode parameter.
3234

35+
- [#51](https://github.com/zendframework/ZendService_Twitter/pull/51) fixes
36+
submission of direct messages to the Twitter API. Payloads for DMs have been
37+
broken since the 3.0.0 release.
38+
3339
## 3.0.1 - 2017-08-17
3440

3541
### Added

TODO.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,9 @@ The following is a list of Twitter API methods not yet implemented:
7171
- users/suggestions
7272
- users/suggestions/:slug
7373
- users/suggestions/:slug/members
74+
75+
## Fixes/functionality updates
76+
77+
- Use `Normalizer` class to get normalized string, and then use that to count
78+
number of characters for purpose of string lengths.
79+
- Update allowed status length to 280 characters.

src/Twitter.php

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ class Twitter
3232
*/
3333
const OAUTH_BASE_URI = 'https://api.twitter.com/oauth';
3434

35+
/**
36+
* Paths that use JSON payloads (vs form-encoded)
37+
*/
38+
const PATHS_JSON_PAYLOAD = [
39+
'direct_messages/events/new',
40+
'direct_messages/welcome_messages/new',
41+
'direct_messages/welcome_messages/rules/new',
42+
];
43+
3544
/**
3645
* 246 is the current limit for a status message, 140 characters are displayed
3746
* initially, with the remainder linked from the web UI or client. The limit is
@@ -402,7 +411,12 @@ public function post(string $path, $data = null) : Response
402411
{
403412
$client = $this->getHttpClient();
404413
$this->init($path, $client);
405-
$response = $this->performPost(Http\Request::METHOD_POST, $data, $client);
414+
$response = $this->performPost(
415+
Http\Request::METHOD_POST,
416+
$data,
417+
$client,
418+
in_array($path, self::PATHS_JSON_PAYLOAD, true)
419+
);
406420
return new Response($response);
407421
}
408422

@@ -1272,6 +1286,7 @@ public function statusesUpdate(string $status, $inReplyToStatusId = null, $extra
12721286
if ($inReplyToStatusId) {
12731287
$params['in_reply_to_status_id'] = $inReplyToStatusId;
12741288
}
1289+
12751290
return $this->post($path, $params);
12761291
}
12771292

@@ -1499,21 +1514,17 @@ protected function validateScreenName(string $name) : string
14991514
* is JSON-encoded before being passed to the request body.
15001515
*
15011516
* @param null|string|array|\stdClass $data Raw data to send
1517+
* @param bool $asJson Whether or not the data should be submitted as JSON
1518+
* (vs form urlencoded, which is the default)
15021519
*/
1503-
protected function performPost(string $method, $data, Http\Client $client) : Http\Response
1520+
protected function performPost(string $method, $data, Http\Client $client, bool $asJson) : Http\Response
15041521
{
1505-
if (is_array($data) || is_object($data)) {
1506-
$data = json_encode($data, $this->jsonFlags);
1507-
}
1522+
$client->setMethod($method);
15081523

1509-
if (! empty($data)) {
1510-
$client->setRawBody($data);
1511-
$client->getRequest()
1512-
->getHeaders()
1513-
->addHeaderLine('Content-Type', 'application/json');
1514-
}
1524+
$asJson
1525+
? $this->prepareJsonPayloadForClient($client, $data)
1526+
: $this->prepareFormPayloadForClient($client, $data);
15151527

1516-
$client->setMethod($method);
15171528
return $client->send();
15181529
}
15191530

@@ -1629,4 +1640,36 @@ protected function createUserListParameter($ids, array $params, string $context)
16291640
$params['screen_name'] = implode(',', $ids);
16301641
return $params;
16311642
}
1643+
1644+
/**
1645+
* Prepare a JSON payload for the HTTP client.
1646+
*/
1647+
private function prepareJsonPayloadForClient(Http\Client $client, $data)
1648+
{
1649+
if (is_array($data) || is_object($data)) {
1650+
$data = json_encode($data, $this->jsonFlags);
1651+
}
1652+
1653+
if (empty($data) || ! is_string($data)) {
1654+
return;
1655+
}
1656+
1657+
$client->getRequest()
1658+
->getHeaders()
1659+
->addHeaderLine('Content-Type', 'application/json');
1660+
1661+
$client->setRawBody($data);
1662+
}
1663+
1664+
/**
1665+
* Prepare a form-url-encoded payload for the HTTP client.
1666+
*/
1667+
private function prepareFormPayloadForClient(Http\Client $client, $data)
1668+
{
1669+
if (! is_array($data)) {
1670+
return;
1671+
}
1672+
1673+
$client->setParameterPost($data);
1674+
}
16321675
}

test/TwitterTest.php

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,16 @@ protected function stubOAuthClient(
6565
$client->setHeaders(['Accept-Charset' => 'ISO-8859-1,utf-8'])->will([$client, 'reveal']);
6666
$client->clearCookies()->will([$client, 'reveal']);
6767
$client->getCookies()->willReturn([]);
68+
6869
if (null !== $params && $method === 'GET') {
6970
$client->setParameterGet($params)->shouldBeCalled();
7071
}
71-
if (null !== $params && $method === 'POST') {
72-
$requestBody = json_encode($params, $this->jsonFlags);
73-
$client->setRawBody($requestBody)->shouldBeCalled();
74-
75-
$headers = $this->prophesize(Http\Headers::class);
76-
$headers->addHeaderLine('Content-Type', 'application/json')->shouldBeCalled();
77-
$request = $this->prophesize(Http\Request::class);
78-
$request->getHeaders()->will([$headers, 'reveal']);
79-
$client->getRequest()->will([$request, 'reveal']);
72+
73+
if ($method === 'POST' && null !== $params) {
74+
$pathMinusExtension = str_replace('.json', '', $path);
75+
in_array($pathMinusExtension, Twitter\Twitter::PATHS_JSON_PAYLOAD, true)
76+
? $this->prepareJsonPayloadForClient($client, $params)
77+
: $this->prepareFormEncodedPayloadForClient($client, $params);
8078
}
8179

8280
$response = $this->prophesize(Http\Response::class);
@@ -103,6 +101,23 @@ protected function stubOAuthClient(
103101
return $client->reveal();
104102
}
105103

104+
protected function prepareJsonPayloadForClient($client, array $params = null)
105+
{
106+
$headers = $this->prophesize(Http\Headers::class);
107+
$headers->addHeaderLine('Content-Type', 'application/json')->shouldBeCalled();
108+
$request = $this->prophesize(Http\Request::class);
109+
$request->getHeaders()->will([$headers, 'reveal']);
110+
$client->getRequest()->will([$request, 'reveal']);
111+
112+
$requestBody = json_encode($params, $this->jsonFlags);
113+
$client->setRawBody($requestBody)->shouldBeCalled();
114+
}
115+
116+
protected function prepareFormEncodedPayloadForClient($client, array $params = null)
117+
{
118+
$client->setParameterPost($params)->will([$client, 'reveal']);
119+
}
120+
106121
public function stubHttpClientInitialization()
107122
{
108123
$client = $this->prophesize(OAuthClient::class);

0 commit comments

Comments
 (0)