diff --git a/CHANGELOG.md b/CHANGELOG.md index d3e823b..1482e2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,12 @@ All notable changes to this project will be documented in this file, in reverse ### Changed +- [#41](https://github.com/zendframework/ZendService_Twitter/pull/41) modifies + how the `Twitter` class sends `POST` requests to send JSON payloads instead of + `application/x-www-form-urlencoded`. All payloads except those for media + uploads support this, and several newer endpoints (such as methods for + allowing direct message media attachments) now require them. + - [#40](https://github.com/zendframework/ZendService_Twitter/pull/40) updates direct message support to set the character limit to 10k, as documented currently for the Twitter API. diff --git a/library/ZendService/Twitter/Twitter.php b/library/ZendService/Twitter/Twitter.php index f0d73ec..052885f 100644 --- a/library/ZendService/Twitter/Twitter.php +++ b/library/ZendService/Twitter/Twitter.php @@ -106,6 +106,13 @@ class Twitter */ protected $username; + /** + * Flags to use with json_encode for POST requests + * + * @var int + */ + private $jsonFlags = JSON_PRESERVE_ZERO_FRACTION | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE; + /** * @param null|array|Traversable $options * @param null|OAuth\Consumer $consumer @@ -1233,7 +1240,7 @@ protected function post($path, $data = null) * * Performs a POST or PUT request. Any data provided is set in the HTTP * client. String data is pushed in as raw POST data; array or object data - * is pushed in as POST parameters. + * is JSON-encoded before being passed to the request body. * * @param mixed $method * @param mixed $data @@ -1241,11 +1248,17 @@ protected function post($path, $data = null) */ protected function performPost($method, $data, Http\Client $client) { - if (is_string($data)) { - $client->setRawData($data); - } elseif (is_array($data) || is_object($data)) { - $client->setParameterPost((array) $data); + if (is_array($data) || is_object($data)) { + $data = json_encode($data, $this->jsonFlags); } + + if (! empty($data)) { + $client->setRawBody($data); + $client->getRequest() + ->getHeaders() + ->addHeaderLine('Content-Type', 'application/json'); + } + $client->setMethod($method); return $client->send(); } diff --git a/tests/ZendService/Twitter/TwitterTest.php b/tests/ZendService/Twitter/TwitterTest.php index 5e69508..c663eaf 100644 --- a/tests/ZendService/Twitter/TwitterTest.php +++ b/tests/ZendService/Twitter/TwitterTest.php @@ -12,6 +12,7 @@ use PHPUnit\Framework\TestCase; use Prophecy\Argument; +use ReflectionProperty; use Zend\Http; use ZendOAuth\Client as OAuthClient; use ZendOAuth\Consumer as OAuthConsumer; @@ -25,6 +26,14 @@ class TwitterTest extends TestCase { + public function setUp() + { + $twitter = new Twitter\Twitter(); + $r = new ReflectionProperty($twitter, 'jsonFlags'); + $r->setAccessible(true); + $this->jsonFlags = $r->getValue($twitter); + } + /** * Quick reusable OAuth client stub setup. Its purpose is to fake * HTTP interactions with Twitter so the component can focus on what matters: @@ -58,9 +67,18 @@ protected function stubOAuthClient( $client->setHeaders(['Accept-Charset' => 'ISO-8859-1,utf-8'])->will([$client, 'reveal']); $client->clearCookies()->will([$client, 'reveal']); $client->getCookies()->willReturn([]); - if (null !== $params) { - $setter = 'setParameter' . ucfirst(strtolower($method)); - $client->$setter($params)->shouldBeCalled(); + if (null !== $params && $method === 'GET') { + $client->setParameterGet($params)->shouldBeCalled(); + } + if (null !== $params && $method === 'POST') { + $requestBody = json_encode($params, $this->jsonFlags); + $client->setRawBody($requestBody)->shouldBeCalled(); + + $headers = $this->prophesize(Http\Headers::class); + $headers->addHeaderLine('Content-Type', 'application/json')->shouldBeCalled(); + $request = $this->prophesize(Http\Request::class); + $request->getHeaders()->will([$headers, 'reveal']); + $client->getRequest()->will([$request, 'reveal']); } $response = $this->prophesize(Http\Response::class);