Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
691 lines (458 sloc)
16.8 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
* TwitterDarValor.php | |
* | |
* Copyright 2013 Miguel Rafael Esteban Martín (www.logicaalternativa.com) <miguel.esteban@logicaalternativa.com> | |
* | |
* This program is free software; you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation; either version 2 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program; if not, write to the Free Software | |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, | |
* MA 02110-1301, USA. | |
*/ | |
require_once dirname(__FILE__).DIRECTORY_SEPARATOR."TwitterAPIExchange.php"; | |
/* | |
* Clase que da valor a los tweet. Calcula el grado de interés la | |
* audiencia y el grado de difusión de los tweet | |
**/ | |
class TwitterDarValor { | |
/* ATRIBUTOS PÚBLICOS */ | |
/* | |
* Url del api de twitterr | |
* */ | |
var $urlApi = "https://api.twitter.com/1.1/"; | |
/* | |
* Factor que da valor a los reteweet a la hora de calcular el grado | |
* de interés. Número mayor que 1 | |
* */ | |
var $factorRetweet = 33; // (3 Retweet por 100 seguidores) darían un grado de interes del 2.5 => la mitad | |
/* | |
* Factor que da valor a los favoritos a la hora de calcular el grado | |
* de interés. Número mayor que 1 | |
* */ | |
var $factorFavoritos = 16; // (6 favoritos por 100 seguidores = 25) darían un grado de interes del 2.5 => la mitad | |
/* | |
* Número de tweets de los que se listan de los que se | |
* obtiene la audiencia | |
* */ | |
var $maxRegistrosCalcularAudiencia = 15; | |
/* | |
* Array de acceso que es necesario para la clase TwitterAPIExchange | |
* Para más información ver: | |
* https://github.com/J7mbo/twitter-api-php/blob/master/README.md | |
* */ | |
private $settings = array( | |
'oauth_access_token' => "", | |
'oauth_access_token_secret' => "", | |
'consumer_key' => "", | |
'consumer_secret' => "" | |
); | |
/* Contador interno que sirve para llevar la cuenta de las | |
* audiencias que ya se han calculado | |
* */ | |
private $contInternoTweetAudiencia = 0; | |
/* | |
* Clase privada de TwitterAPIExchange | |
* Para más información ver: | |
* https://github.com/J7mbo/twitter-api-php/blob/master/README.md | |
* */ | |
private $twitterAPIExchange; | |
/* | |
* Constructor | |
* */ | |
function __construct( $settings = null ) { | |
if ( ! is_null( $settings ) ) { | |
$this->settings = $settings; // Se carga los "settings" para la conexión | |
} | |
// Se crea la instancia de la clase | |
$this->twitterAPIExchange = new TwitterAPIExchange( $this->settings ); | |
} | |
/*MÉTODOS PÚBLICOS*/ | |
/* | |
* Obtiene el time line (la parte pública) del usuario validado en | |
* los settings | |
* Se puede pasar el número de tweets que se quieren obtener y | |
* si se desea obtener la audiencia y el grado de difusión | |
* */ | |
public function obtenerTimeLine( $numeroTweets = 8, $obtenerAudiencia = false ) { | |
$this->_inicializarContadorTweetInternoAudiencia(); | |
$resultadoTwitter = $this->_obtenerTimeLineTwitter( $numeroTweets ); | |
return $this->_procesarTimeLine( $resultadoTwitter, $obtenerAudiencia ); | |
} | |
/* | |
* Obtiene el home time line (la parte privada) del usuario validado | |
* en los settings | |
* Se puede pasar el número de tweets que se quieren obtener y | |
* si se desea obtener la audiencia y el grado de difusión | |
* */ | |
public function obtenerHomeTimeLine( $numeroTweets = 8, $obtenerAudiencia = false ) { | |
$this->_inicializarContadorTweetInternoAudiencia(); | |
$resultadoTwitter = $this->_obtenerHomeTimeLineTwitter( $numeroTweets ); | |
return $this->_procesarTimeLine( $resultadoTwitter, $obtenerAudiencia ); | |
} | |
/*MÉTODOS PRIVADOS*/ | |
/* | |
* Obtiene el home time line haciendo una llamada REST al API de | |
* Se pasa por argumento el número de tweets que se quiere devolver | |
* */ | |
private function _obtenerHomeTimeLineTwitter( $numeroTweets ){ | |
$url = "{$this->urlApi}statuses/home_timeline.json"; | |
$camposGet = "?count=$numeroTweets"; | |
$metodo = "GET"; | |
$request = $this->twitterAPIExchange->setGetfield($camposGet ) | |
->buildOauth($url, $metodo) | |
->performRequest(); | |
$res = json_decode( $request ) ; | |
// Traza | |
//~ var_dump( $res ); | |
//~ exit; | |
// Fin de traza | |
return $res; | |
} | |
/* | |
* Obtiene el time line haciendo una llamada REST al API de | |
* Se pasa por argumento el número de tweets que se quiere devolver | |
* */ | |
private function _obtenerTimeLineTwitter( /*$usuario, */$numeroTweets ){ | |
$url = "{$this->urlApi}statuses/user_timeline.json"; | |
//~ $camposGet = "?screen_name=$usuario&count=$numeroTweets"; | |
$camposGet = "?count=$numeroTweets"; | |
$metodo = "GET"; | |
$request = $this->twitterAPIExchange->setGetfield($camposGet ) | |
->buildOauth($url, $metodo) | |
->performRequest(); | |
$res = json_decode( $request ) ; | |
// Traza | |
//~ var_dump( $res ); | |
//~ exit; | |
// Fin de traza | |
return $res; | |
} | |
/* | |
* Si el mensaje que se está procesado es un retweet, se obtiene | |
* la fecha, el nombre y el perfil del que lo ha hecho | |
* */ | |
private function _obtenerDatosRetweet( $registroProcesado, $reg ){ | |
if ( ! isset ( $registroProcesado["es_retweet"] ) || $registroProcesado["es_retweet"] != 1) { | |
return $registroProcesado; | |
} | |
$registroProcesado["retweet_fecha_unix"] = strtotime( $reg->created_at ); | |
// Se obtiene la clase usuario del tweet | |
$tweetUsuario = $reg->user; | |
if ( isset( $tweetUsuario) ) { | |
$registroProcesado["retweet_nombre" ] = $tweetUsuario->name; | |
$registroProcesado ["retweet_perfil" ] = $tweetUsuario->screen_name; | |
} | |
return $registroProcesado; | |
} | |
/* | |
* Inicializa el contador interno de audiencia | |
* */ | |
private function _inicializarContadorTweetInternoAudiencia(){ | |
$this->contInternoTweetAudiencia = 0; | |
} | |
/* | |
* Procesa el registro que nos devueleve el api REST para devolver | |
* los datos que nos son interesantes | |
* Devuelve una lista con los datos procesados y que nos son | |
* interesantes de cada registro que nos devuelve el API REST | |
* */ | |
private function _procesarTimeLine( $res, $obtenerAudiencia ) { | |
$resProcesado = array(); | |
foreach ( $res as $registro ) { | |
$registroProcesado = array(); | |
// Obtiene la clase según es retweet o no | |
$registroProcesado["es_retweet"] = isset ($registro->retweeted_status) ? 1 : 0; | |
$registroProcesado = $this->_obtenerDatosRetweet( $registroProcesado, $registro ) ; | |
$registroProcesado = $this->_cargarDatosTweet( $registroProcesado, $registro ) ; | |
$registroProcesado = $this->_obtenerGradoInteres( $registroProcesado ); | |
if ( $obtenerAudiencia ) { | |
if ( $this->contInternoTweetAudiencia < $this->maxRegistrosCalcularAudiencia ) { | |
$registroProcesado = $this->_obtenerAudiencia( $registroProcesado ); | |
$registroProcesado = $this->_obtenerGradoDifusion( $registroProcesado ); | |
$this->contInternoTweetAudiencia ++; | |
} | |
} | |
//~ // Traza | |
// var_dump( $registroProcesado); | |
//~ var_dump( $tweet->entities); | |
// exit; | |
//~ // Fin de traza | |
$resProcesado[] = $registroProcesado; | |
} | |
return $resProcesado; | |
} | |
/* | |
* Carga los datos del tweetcomo la fecha, el texto, el número de | |
* retweet,... | |
* */ | |
private function _cargarDatosTweet( $registroProcesado, $registro ){ | |
$tweet = $registroProcesado["es_retweet"] == 1 ? $registro->retweeted_status : $registro; | |
$registroProcesado[ "fecha_unix"] = strtotime ( $tweet->created_at ) ; | |
//~ $registroProcesado[ "fecha"] = $this->_calcularFecha( $registroProcesado[ "fecha_unix"] ); | |
$registroProcesado[ "texto"] = $tweet->text; | |
$registroProcesado[ "textoHtml"] = $this->_obtenerTextoHtml( $tweet->text, $tweet->entities ); | |
$registroProcesado[ "num_retweet"] = $tweet->retweet_count; | |
$registroProcesado[ "num_favoritos"] = $tweet->favorite_count; | |
$registroProcesado[ "id"] = $tweet->id_str; | |
// Traza | |
/* | |
var_dump( $registroProcesado); | |
var_dump( $tweet->id_str ); | |
exit; | |
*/ | |
//~ // Fin de traza | |
// Se obtienen los datos del usuario | |
$registroProcesado = $this->_obtenerDatosAutorTweet( $registroProcesado, $tweet ); | |
return $registroProcesado; | |
} | |
/* | |
* Obtiene el grado de difusión. | |
* Es la proporción de seguidores con repespecto a la audiencia total | |
* Se eleva al cuadrado para dar más importancia a las proporciones | |
* altas | |
* Es un número normalizado, del 0 (peor) al 5 (mejor) | |
* */ | |
private function _obtenerGradoDifusion( $registroProcesado ){ | |
if ( ! isset ( $registroProcesado["audiencia"] ) ){ | |
return $registroProcesado; | |
} | |
$coeficiente = 1 - ( $registroProcesado["autor_seguridores"] / $registroProcesado["audiencia"] ) ; | |
$coeficiente = $coeficiente * $coeficiente; | |
$coeficiente = $coeficiente * 5; | |
$registroProcesado["grado_difusion"] =$this->_redondear( $coeficiente, 0.5 ); | |
return $registroProcesado; | |
} | |
/* | |
* Obtiene la audiencia del tweet suma los seguidores de los | |
* últimos 100 retweet. | |
* Si el tweet tiene más de 100 retweet se hace una estimación con | |
* el número calculado. | |
* */ | |
private function _obtenerAudiencia( $registroProcesado ) { | |
$numeroSeguidores = 0; | |
if ( isset( $registroProcesado[ "num_retweet"] ) | |
&& $registroProcesado[ "num_retweet"] > 0) { | |
$numeroSeguidores = $this->_obtenerSumaSeguidores( $registroProcesado[ "id"], $registroProcesado[ "num_retweet"] ); | |
if ( isset( $numeroSeguidores ) && $registroProcesado[ "num_retweet"] > 100) { // Se hace una estimación | |
$numeroSeguidores = round ( $numeroSeguidores * $registroProcesado[ "num_retweet"] / 100 ); | |
$numeroSeguidores = $numeroSeguidores + $registroProcesado[ "autor_seguridores" ]; | |
$registroProcesado["audiencia"] = $this->_redondearCifrasSignificativas( $numeroSeguidores, 4 ); | |
return $registroProcesado; | |
} | |
} | |
// Traza | |
//~ var_dump( $registroProcesado[ "num_retweet"] ); | |
//~ var_dump( $numeroSeguidores ); | |
//~ exit; | |
// Fin de traza | |
$registroProcesado["audiencia"] = isset ( $numeroSeguidores ) | |
? ( $registroProcesado[ "autor_seguridores" ] + $numeroSeguidores ) | |
: null; | |
return $registroProcesado; | |
} | |
/* | |
* Para la estimación redondea a las cifras significativas | |
* que se pasan como argumento | |
* */ | |
private function _redondearCifrasSignificativas( $valor, $cifrasSignificativas ){ | |
$res = $valor; | |
$i = 0; | |
while ( $res > 1 ) { | |
$res = $res / 10; | |
$i++; | |
} | |
if ( $i <= $cifrasSignificativas ) { | |
return $valor; | |
} | |
$res = round ( $res * pow( 10, $cifrasSignificativas ) ) / pow( 10, $cifrasSignificativas ); | |
$res = $res *pow( 10, $i); | |
// Traza | |
/* | |
var_dump( $valor ); | |
var_dump( $res ); | |
exit(); | |
*/ | |
// Fin de traza | |
return $res; | |
} | |
/* | |
* Obtiene la suma de los seguidores de los últimos 100 retweet | |
* del tweet que se pasa como argumento | |
* */ | |
private function _obtenerSumaSeguidores( $id, $numero ){ | |
$res = $this->_obtenerRetweets( $id, $numero ) ; | |
$numeroSeguidores = 0; | |
if ( !isset( $res ) || ! is_array( $res ) ) { | |
return null ; | |
} | |
foreach ( $res as $registro ) { | |
$tweetUsuario = $registro->user; | |
if ( isset( $tweetUsuario ) ) { | |
// Traza | |
//~ var_dump( $tweetUsuario->name.": ".$tweetUsuario->followers_count); | |
// Fin de traza | |
$num = $tweetUsuario->followers_count; | |
if ( isset( $numeroSeguidores ) ) { | |
$numeroSeguidores += $num; | |
} | |
} | |
} | |
return $numeroSeguidores; | |
} | |
/* | |
* Obtiene el número de retweets del id que se pasa haciendo una | |
* llamada al API Rest de Twitter | |
* El número está limitado a 100 | |
* */ | |
private function _obtenerRetweets( $id, $numero ) { | |
$url = "{$this->urlApi}statuses/retweets/{$id}.json"; | |
$count = $numero > 100 ? 100 : $numero; | |
$camposGet = "?count=$count"; | |
$metodo = "GET"; | |
$request = $this->twitterAPIExchange->setGetfield($camposGet ) | |
->buildOauth($url, $metodo) | |
->performRequest(); | |
$res = json_decode( $request ) ; | |
// Traza | |
//~ var_dump( $res ); | |
//~ exit; | |
// Fin de Traza | |
return $res; | |
} | |
/* | |
* Redondea un número con la precisión requerida | |
* */ | |
private function _redondear( $avalor, $precision ) { | |
$valor = ( $avalor + ( $precision / 2 ) ) / $precision; | |
// Taza | |
/* | |
var_dump( $avalor ); | |
var_dump( $valor ); | |
var_dump( floor( $valor ) * $precision ); | |
*/ | |
// Fin de traza | |
return floor( $valor ) * $precision; | |
} | |
/* | |
* Obtiene el grado de interés. | |
* Se obtiene el valor resultante de la suma de multiplicar el | |
* número de retwet y de favoritos por sus respectivos factores. | |
* Después se obtiene que proporción es con respecto a sus seguidores | |
* Se normaliza a un número de 0 (peor) a 5 (mejor) con una precisión | |
* de 0.5 | |
* */ | |
private function _obtenerGradoInteres( $registroProcesado ) { | |
$coeficienteRetweet = ( $this->factorRetweet * $registroProcesado["num_retweet"] ) + ( $this->factorFavoritos * $registroProcesado["num_favoritos"] ); | |
$coeficiente = $coeficienteRetweet / ( $coeficienteRetweet + $registroProcesado["autor_seguridores"] ); | |
// Se normaliza a un valor entre 0,5 y 5 con precision de 0,5 | |
$coeficiente = 5 * $coeficiente; | |
$registroProcesado["grado_interes"] = $this->_redondear( $coeficiente, 0.5 ); | |
// Traza | |
//~ $registroProcesado["coeficienteRetweet"] = $coeficienteRetweet; | |
//~ $registroProcesado["coeficiente"] = $coeficiente; | |
//~ var_dump( $coeficienteRetweet ); | |
//~ var_dump( $coeficiente ); | |
//~ exit; | |
// Fin de traza | |
return $registroProcesado; | |
} | |
/* | |
* Obtiene los datos del autor del Tweet | |
* */ | |
private function _obtenerDatosAutorTweet( $registroProcesado, $tweet ) { | |
$tweetUsuario = $tweet->user; | |
// Traza | |
//~ var_dump( $tweetUsuario); | |
// Fin de traza | |
$registroProcesado ["autor_imagen"] = $tweetUsuario->profile_image_url; | |
$registroProcesado ["autor_nombre" ] = $tweetUsuario->name; | |
$registroProcesado ["autor_perfil" ] = $tweetUsuario->screen_name; | |
$registroProcesado ["autor_seguridores" ] = $tweetUsuario->followers_count; | |
// Traza | |
//~ var_dump( $registroProcesado); | |
//~ exit; | |
// Fin de traza | |
return $registroProcesado; | |
} | |
/* | |
* Procesa las urls para mostarlas en html | |
* */ | |
private function _procesarUrls( $texto, $urls ) { | |
if ( ! isset ( $urls ) || ! is_array( $urls ) ) { | |
return $texto; | |
} | |
// Traza | |
//~ var_dump( $urls); | |
//~ exit; | |
//~ // Fin de traza | |
foreach ( $urls as $reg ) { | |
$texto = str_replace( $reg->url, "<a href=\"{$reg->expanded_url}\" target=\"_blank\">{$reg->display_url}</a>", $texto ); | |
} | |
return $texto; | |
} | |
/* | |
* Procesa el texto del tweet como HTML, procesa los Hashtag, | |
* los usuarios y las URLs | |
* */ | |
private function _obtenerTextoHtml( $texto, $entities) { | |
$texto = $this->_procesarUrls( $texto, $entities->urls ); | |
if ( isset( $entities->media ) ) { | |
$texto = $this->_procesarUrls( $texto, $entities->media ); | |
} | |
$texto = $this->_procesarEnlaceHtmlHashtag( $texto ); | |
$texto = $this->_procesarEnlaceHtmlPerfil( $texto ); | |
// Traza | |
//~ var_dump($texto); | |
//~ exit; | |
// Fin de Traza | |
return nl2br( $texto ); | |
} | |
/* | |
* Procesa un Hashtag para mostrar su enlace HTML | |
* */ | |
private function _procesarEnlaceHtmlHashtag( $texto ) { | |
$patron = '/(^|[ "\n\r\'])(#([a-zA-Z0-9_-]+))/i'; | |
$url = "https://twitter.com/search?q=%23"; | |
return $this->_procesarEnlacesHtmlRegExp( $texto, $patron, $url ); | |
} | |
/* | |
* Procesa un nombre de usuario para mostrar su enlace HTML | |
* */ | |
private function _procesarEnlaceHtmlPerfil( $texto ) { | |
$patron = '/(^|[ "\n\r\'])(@([a-zA-Z0-9_-]+))/i'; | |
$url = "https://twitter.com/"; | |
return $this->_procesarEnlacesHtmlRegExp( $texto, $patron, $url ); | |
} | |
/* | |
* Procesa el texto con la empresión regular para obtener enlace | |
* del código html | |
* */ | |
private function _procesarEnlacesHtmlRegExp( $texto, $patron, $url ) { | |
$match = array(); | |
$resultado = preg_match_all( $patron, $texto , $match, PREG_SET_ORDER ); | |
foreach ( $match as $coincidencias ) { | |
// Traza | |
// print_r($match); | |
// exit; | |
// Fin de Traza | |
if ( isset ( $coincidencias[2] ) && isset( $coincidencias[3] ) ){ | |
$paramEncode = urlencode( $coincidencias[3] ); | |
$valor = $coincidencias[2]; | |
$texto = str_replace( $valor, "<a href=\"{$url}{$paramEncode}\" target=\"_blank\">${valor}</a>", $texto ); | |
} | |
} | |
return trim( $texto ); | |
} | |
} |