_selectOptions['order'] = 'createdAt DESC';
$this->_selectOptions['limitPage'] = [0, (int)$this->getConfig('showCount', 10)];
return $this;
}
protected function _getFromColumns()
{
return ['id', 'tweetId', 'userId', 'name', 'screenName', 'imageUrl',
'retwittedByName', 'retwittedByScreenName', 'createdAt', 'html'];
}
protected function _prepareRow(array &$row)
{
parent::_prepareRow($row);
$row['timeAgo'] = $this->_getTimeAgo($row['createdAt']);
return $this;
}
/**
* Returns last twit in DB (for any user)
* @return mixed
*/
protected function _getLastTweet()
{
$select = $this->_db->select();
$select->from($this->_getPair());
$select->order('createdAt DESC');
$select->limit(1);
return $this->_db->fetchRow($select);
}
/**
* Reads latest tweets from users timeline and inserts its to DB
* @return bool
*/
public function updateTweets()
{
if (null == ($tweets = $this->readTimeline())) {
$this->_addError(static::MSG_NO_TWEETS);
return true;
}
$tweets = $this->_convertTweets($tweets);
$this->_db->beginTransaction();
try {
$this->_getTable()->delete([]);
foreach ($tweets as $tweet) {
$tweet['raw'] = serialize($tweet['raw']);
$this->_getTable()->insert($tweet);
}
$this->_db->commit();
} catch (Exception $e) {
$this->_db->rollBack();
Qs_Debug::processException($e);
return false;
}
return true;
}
/**
* @param array $tweetList RAW Tweets (twitter format)
* @return array
*/
protected function _convertTweets($tweetList)
{
$result = [];
$tweetList = array_reverse($tweetList);
foreach ($tweetList as $tweet) {
$data = (empty($tweet['retweeted_status'])) ? $tweet : $tweet['retweeted_status'];
$result[] = [
'tweetId' => $data['id_str'],
'userId' => $data['user']['id_str'],
'name' => $data['user']['name'],
'screenName' => $data['user']['screen_name'],
'imageUrl' => preg_replace('/^\w+:/', '', $data['user']['profile_image_url']),
'retwittedByName' => (empty($tweet['retweeted_status'])) ? null : $tweet['user']['name'],
'retwittedByScreenName' => (empty($tweet['retweeted_status'])) ? null : $tweet['user']['screen_name'],
'createdAt' => date('Y-m-d H:i:s', strtotime($data['created_at'])),
'text' => $data['text'],
'html' => empty($data['entities'])
? htmlspecialchars($data['text'])
: $this->_prepareTextEntities($data['text'], $data['entities']),
'source' => $data['source'],
'raw' => $tweet,
];
}
return $result;
}
/**
* @param string $lastDate
* @return bool|null|string
*/
protected function _getTimeAgo($lastDate)
{
$lastDate = new DateTime($lastDate);
$date = new DateTime();
if ($date->getTimestamp() - $lastDate->getTimestamp() > 86400) { // more that 24h ago
$result = $lastDate->format('M d');
} else {
$diff = $lastDate->diff($date);
$parts = 0;
$ranges = ['d' => 'day', 'h' => 'hour', 'i' => 'minute'];
$result = '';
foreach ($ranges as $idx => $name) {
if ($diff->{$idx}) {
$result .= ' ' . $diff->{$idx} . ' ' . $name . ($diff->{$idx} > 1 ? 's' : '');
if (++$parts > 2) {
break;
}
}
}
if ('' == $result) {
$result = 'moment ago';
} else {
$result = 'about ' . ltrim($result) . ' ago';
}
}
return $result;
}
/**
* Replaces tweets entities in text
*
* @param string $text Tweet plain text
* @param array $entities @see https://dev.twitter.com/docs/tweet-entities
* @return string HTML code
*/
protected function _prepareTextEntities($text, array $entities)
{
$replacements = [];
foreach ($entities as $area => $items) {
$pattern = $params = null;
switch ($area) {
case 'hashtags':
$pattern = '#%s';
$params = ['text'];
break;
case 'user_mentions':
$pattern = '@%s';
$params = ['screen_name', 'screen_name'];
break;
case 'media':
case 'urls':
$pattern = '%s';
$params = ['expanded_url', 'display_url'];
break;
default:
break;
}
foreach ($items as $item) {
$values = [];
foreach ($params as $name) {
$values[] = htmlspecialchars($item[$name]);
}
$replacements[] = [
'indices' => [$item['indices'][0], $item['indices'][1]],
'pattern' => $pattern,
'params' => $values
];
}
}
usort(
$replacements, function ($a, $b) {
$a = $a['indices'][0];
$b = $b['indices'][0];
if ($a == $b) {
return 0;
}
return ($a < $b) ? -1 : 1;
}
);
$result = '';
$index = 0;
foreach ($replacements as $info) {
$indices = $info['indices'];
$result .= mb_substr($text, $index, $indices[0] - $index);
$result .= vsprintf($info['pattern'], $info['params']);
$index = $indices[1];
}
$result .= mb_substr($text, $index, mb_strlen($text) - $index);
return $result;
}
}