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

Commit

Permalink
Merge branch 'hotfix/280-characters'
Browse files Browse the repository at this point in the history
Close #55
  • Loading branch information
weierophinney committed Nov 21, 2017
2 parents f79fe8c + abd27f0 commit bf2659e
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 24 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 3.0.2 - TBD
## 3.0.2 - 2017-11-21

### Added

- Nothing.
- [#55](https://github.com/zendframework/ZendService_Twitter/pull/55) adds
support for 280-character tweets.

### Changed

Expand Down
6 changes: 0 additions & 6 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,3 @@ The following is a list of Twitter API methods not yet implemented:
- users/suggestions
- users/suggestions/:slug
- users/suggestions/:slug/members

## Fixes/functionality updates

- Use `Normalizer` class to get normalized string, and then use that to count
number of characters for purpose of string lengths.
- Update allowed status length to 280 characters.
37 changes: 21 additions & 16 deletions src/Twitter.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
namespace ZendService\Twitter;

use Closure;
use Normalizer;
use Traversable;
use ZendOAuth as OAuth;
use Zend\Http;
Expand All @@ -19,6 +20,15 @@
*
* Note: most `$id` parameters accept either string or integer values. This is
* due to the fact that identifiers in the Twitter API may exceed PHP_INT_MAX.
*
* Note on character counting: Twitter accepts UTF-8 encoded text via the API,
* and counts multi-byte characters as a single character. PHP's strlen(),
* however, treats each byte as a character for purposes of determing the
* string length. To get around that, we can pass the message to utf8_decode,
* which will replace any multi-byte characters with a `?`; this works fine
* for counting lengths.
*
* @see https://developer.twitter.com/en/docs/basics/counting-characters
*/
class Twitter
{
Expand All @@ -42,14 +52,9 @@ class Twitter
];

/**
* 246 is the current limit for a status message, 140 characters are displayed
* initially, with the remainder linked from the web UI or client. The limit is
* applied to a html encoded UTF-8 string (i.e. entities are counted in the limit
* which may appear unusual but is a security measure).
*
* This should be reviewed in the future...
* As of November 2017, the character limit for status messages is 280.
*/
const STATUS_MAX_CHARACTERS = 246;
const STATUS_MAX_CHARACTERS = 280;

/**
* @var array
Expand Down Expand Up @@ -586,7 +591,7 @@ public function directMessagesEventsNew($user, string $text, array $extraParams
{
$path = 'direct_messages/events/new';

$len = iconv_strlen($text, 'UTF-8');
$len = strlen(utf8_decode($text));
if (0 === $len) {
throw new Exception\InvalidArgumentException(
'Direct message must contain at least one character'
Expand Down Expand Up @@ -980,7 +985,7 @@ public function searchTweets(string $query, array $options = []) : Response
{
$path = 'search/tweets';

$len = iconv_strlen($query, 'UTF-8');
$len = strlen(utf8_decode($query));
if (0 == $len) {
throw new Exception\InvalidArgumentException(
'Query must contain at least one character'
Expand Down Expand Up @@ -1260,13 +1265,13 @@ public function statusesShow($id, array $options = []) : Response
public function statusesUpdate(string $status, $inReplyToStatusId = null, $extraAttributes = []) : Response
{
$path = 'statuses/update';
$len = iconv_strlen(htmlspecialchars($status, ENT_QUOTES, 'UTF-8'), 'UTF-8');
$len = strlen(utf8_decode($status));
if ($len > self::STATUS_MAX_CHARACTERS) {
throw new Exception\OutOfRangeException(
'Status must be no more than '
. self::STATUS_MAX_CHARACTERS
. ' characters in length'
);
throw new Exception\OutOfRangeException(sprintf(
'Status must be no more than %d characters in length; received %d',
self::STATUS_MAX_CHARACTERS,
$len
));
} elseif (0 == $len) {
throw new Exception\InvalidArgumentException(
'Status must contain at least one character'
Expand Down Expand Up @@ -1392,7 +1397,7 @@ public function usersSearch(string $query, array $options = []) : Response
{
$path = 'users/search';

$len = iconv_strlen($query, 'UTF-8');
$len = strlen(utf8_decode($query));
if (0 == $len) {
throw new Exception\InvalidArgumentException(
'Query must contain at least one character'
Expand Down
14 changes: 14 additions & 0 deletions test/TwitterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,20 @@ public function testPostStatusUpdateToLongShouldThrowException()
$twitter->statuses->update('Test Message - ' . str_repeat(' Hello ', 140));
}

public function testStatusUpdateShouldAllow280CharactersOfUTF8Encoding()
{
$message = str_repeat('é', 280);
$twitter = new Twitter\Twitter;
$twitter->setHttpClient($this->stubOAuthClient(
'statuses/update.json',
Http\Request::METHOD_POST,
'statuses.update.json',
['status' => $message]
));
$response = $twitter->statuses->update($message);
$this->assertInstanceOf(TwitterResponse::class, $response);
}

public function testPostStatusUpdateEmptyShouldThrowException()
{
$this->expectException(Twitter\Exception\ExceptionInterface::class);
Expand Down

0 comments on commit bf2659e

Please sign in to comment.