Actualiza tu theme de WordPress desde SVN

Si trabajas realizando proyectos en WordPress en el que el código se aloja en un servidor usando SVN, una forma sencilla de actualizar tu theme con los últimos cambios es mediante este sencillo y no-seguro plugin.

El plugin añade una opción de menú al Settings del Dashboard de WP, el cual te servirá para indicar el servidor SVN, usuario, contraseña y el path que corresponde a la carpeta themes de WP. El plugin se conectará al repositorio SVN y recuperará las carpetas que se encuentran en el path anterior y comprobará si las carpetas corresponden a themes instalados, mostrarás una lista con los themes encontrados junto a un botón que permite actualizar todo el theme.

Digo que no es seguro porque no controlo los permisos de los usuarios ni otras cuestiones, pero si estás interesado en ello supongo que no te costará mucho meterle mano al código:

// Adding Admin menu
if ( is_admin() ){
  add_action('admin_menu', 'svn_update_menu');
  add_action( 'admin_init', 'svn_update_register_settings' );
 
}
 
function svn_update_register_settings() {
  register_setting( 'svn_up_option-group', 'svn_username' );
  register_setting( 'svn_up_option-group', 'svn_password' );
  register_setting( 'svn_up_option-group', 'svn_repository' );
  register_setting( 'svn_up_option-group', 'svn_theme_path' );
  if ($_GET['page'] == 'svn-update/svn-update.php') {
    require ('phpsvnclient/phpsvnclient.php');
    $phpsvnclient = new phpsvnclient(get_option('svn_repository'), get_option('svn_username'), get_option('svn_password'));
    $files = $phpsvnclient->getDirectoryFiles('/');
    $svn_themes = array();
 
    $themes = array();
 
    foreach(get_themes() as $k=>$t) $themes[$t['Template']] = array($k, $t["Template Dir"]);
 
    if (is_array($files)) {
      foreach($files as $f) {
        if ($f['type'] == 'directory') {
          if (isset($themes[$f['path']])) $svn_themes[$f['path']] = $themes[$f['path']];
        }
      }
    }
    update_option('svn_themes', $svn_themes);
    if (isset($_GET['svn_update'])) {
      $path = $_GET['svn_update'];
      $theme_path = WP_CONTENT_DIR . '/themes/';
      $files = $phpsvnclient->getDirectoryFiles($path);
      foreach($files as $f) {
        if ($f['type'] == 'file') {
          file_put_contents($theme_path.$f['path'], $phpsvnclient->getFile($f['path']));
        }
      }
      add_action('admin_notices', 'showSVNUpdated');
    }
  }
}
 
function showSVNUpdated() {
  echo '<div id="message" class="updated fade"><p><strong>Theme updated</strong></p></div>';
}
 
function svn_update_menu() {
  add_options_page('SVN Update Options', 'SVN Update', 8, __FILE__, 'svn_update_options');
}
 
function svn_update_options() {
?>
<div class="wrap">
<h2>SVN Update Options</h2>
<form method="post" action="options.php">
<?php settings_fields('svn_up_option-group'); ?>
<table class="form-table">
 <tr>
     <th scope="row" valign="top">Username</th>
     <td>
         <input id="svn_username" name="svn_username" value="<?php echo get_option('svn_username'); ?>" type="text"/>
           <label for="svn_username">Write your SVN username</label>
     </td>
 </tr>
 <tr>
     <th scope="row" valign="top">Password</th>
     <td>
         <input id="svn_username" name="svn_password" value="<?php echo get_option('svn_password'); ?>" type="password" />
           <label for="svn_password">Write your SVN password</label>
     </td>
 </tr>
 <tr>
     <th scope="row" valign="top">Repository</th>
     <td>
         <input id="svn_username" name="svn_repository" value="<?php echo get_option('svn_repository'); ?>" type="text" />
           <label for="svn_reposotoy">for example: <em>http://domain.com/svn_path/project</em></label>
     </td>
 </tr>
 <tr>
     <th scope="row" valign="top">Theme path</th>
     <td>
         <input id="svn_username" name="svn_theme_path" value="<?php echo get_option('svn_theme_path'); ?>" type="text" />
           <label for="svn_theme_path">for example: <em>/trunk/my_project/themes</em></label>
     </td>
 </tr>
</table>
<p class="submit">
<input type="submit" class="button-primary" value="<?php _e('Save Changes') ?>" />
</p>
</form>
</div>
<h3>Available Themes</h3>
<?php 
  $themes = get_option('svn_themes'); 
  if (empty($themes)) {
    echo '<p>No themes found in SVN repository instaled in WordPress</p>';
  } else {
    echo '<ul>';
    foreach($themes as $k=>$t) {
      echo '<li>/'.$k.' => '.$t[0].' <a href="'.admin_url('options-general.php?page=svn-update%2Fsvn-update.php&svn_update=/'.$k).'" class="button-primary">Update</a></li>';
    }
    echo '</ul>';
  }
?>
 
<?php
}

Este plugin necesita la librería PHP SVN Client para acceder al SVN, tan solo hay que meterlo en el mismo directorio que el plugin. Le faltan muchas cosas al plugin, pero ni tengo ganas ni tengo tiempo.

Share Button

Acceder a Streaming API de PHP

Para aquellos que necesiten realizar aplicaciones sobre Twitter que tiren de la Streaming API, por ejemplo monitorear o que se dice de una marca, les va a venir muy bien este código:

set_time_limit(0);
 
$query_data = array('track' => 'lo que quieres buscar');
$user = 'username';	// replace with your account
$pass = 'password';	// replace with your account
 
$fp = fsockopen("stream.twitter.com", 80, $errno, $errstr, 30);
if(!$fp){
	print "$errstr ($errno)\n";
} else {
	$request = "GET /1/statuses/filter.json?" . http_build_query($query_data) . " HTTP/1.1\r\n";
	$request .= "Host: stream.twitter.com\r\n";
	$request .= "Authorization: Basic " . base64_encode($user . ':' . $pass) . "\r\n\r\n";
	fwrite($fp, $request);
	while(!feof($fp)){
		$json = fgets($fp);
		$data = json_decode($json, true);
		if($data){
			//
			// Do something with the data!
			//
		}
	}
	fclose($fp);
}

El parámetro track se puede cambiar por follow (usando IDs numéricos) para saber que dice algún usuario y que dicen los que le mencionan o retuitean.

Vía / AF-Design

Share Button

Añadir clase a la imagen destacada de WordPress según el tamaño

Hace bastante que no escribía, sobre todo por falta de tiempo, pero quería escribir sobre este pequeño truco de WordPress. Cuando añadimos una imagen destacada en un post de WordPress nos podemos encontrar con que la imagen ocupa todo el ancho (lo más normal) o que no ocupa tanto, con lo que nos encontramos que la imagen queda muy sola y el diseño queda feo.

Para solucionar esto, deberemos añadir un filtro, comprobar el tamaño de la imagen y el del ancho del contenido y en el caso de que creamos que es conveniente (por ejemplo la mitad del ancho del contenido) añadir una clase a la imagen:

function mi_post_thumbnail_html($html) {
  // Se suele recomendar definir la variable $content_width para ocasiones como esta
  global $content_width;
  preg_match('#width="([^"]+)"#', $html, $s);
  if (isset($s[1]) && $s[1] < $content_width/2) {
    preg_match('#class="([^"]+)"#', $html, $c);
    if (isset($c[1]) && strpos($c[1], "right") === FALSE) {
      return str_replace('class="'.$c[1].'"', 'class="'.$c[1].' right"', $html);
    }
  }
  return $html;
}
add_filter('post_thumbnail_html', 'mi_post_thumbnail_html');
Share Button

Librería PHP para TwitPic

TwitPic es un servicio que se utiliza para subir fotos que luego publicas en Twitter. Si estás realizando una aplicación que tira de Twitter y quieres dar la oportunidad al usuario de subir sus fotos puedes hacer uso de esta aplicación y su API (es necesario darse de alta):

$twitpic = new TwitPic($api_key, $consumer_key, $consumer_secret, $oauth_token, $oauth_secret);
try {
  /*
  * Retrieves all images where the user is facetagged
  */
  $user = $twitpic->faces->show(array('user'=>'meltingice'));
  print_r($user->images);
 
  $media = $twitpic->media->show(array('id'=>1234));
  echo $media->message;
 
  $user = $twitpic->users->show(array('username'=>'meltingice'), array('process'=>false, 'format'=>'xml'));
  echo $user; // raw XML response data
 
  /*
  * Uploads an image to TwitPic
  */
  $resp = $twitpic->upload(array('media'=>'path/to/file.jpg', 'message'=>'This is an example'));
  print_r($resp);
 
  /*
  * Uploads an image to TwitPic AND posts a tweet
  * to Twitter.
  *
  * NOTE: this still uses v2 of the TwitPic API. This means that the code makes 2 separate
  * requests: one to TwitPic for the image, and one to Twitter for the tweet. Because of this,
  * understand this call may take a bit longer than simply uploading the image.
  */
  $resp = $twitpic->uploadAndPost(array('media'=>'path/to/file.jpg', 'message'=>'Another example'));
  print_r($resp);
  
} catch (TwitPicAPIException $e) {
  echo $e->getMessage();
}

TwitPic API for PHP

Share Button

phpcassa: librería PHP para Cassandra

Aunque (afortunadamente) Cassandra ya no está tan de moda y en boca de todos, sigue siendo una herramienta a tener en cuenta a la hora de desarrollar un proyecto en el que se calcule un elevado nivel de datos. Para los que usamos PHP nos vendrá muy bien esta librería que nos facilitará el trabajo y que además es compatible con TimeUUID y SuperColumnFamily:

<?php
// Copiar todos los ficheros en el directorio
define('THRIFT_ROOT', dirname(__FILE__) . '/include/thrift/');
require_once THRIFT_ROOT.'/packages/cassandra/Cassandra.php';
require_once THRIFT_ROOT.'/transport/TSocket.php';
require_once THRIFT_ROOT.'/protocol/TBinaryProtocol.php';
require_once THRIFT_ROOT.'/transport/TFramedTransport.php';
require_once THRIFT_ROOT.'/transport/TBufferedTransport.php';
include_once(dirname(__FILE__) . '/include/phpcassa.php');
include_once(dirname(__FILE__) . '/include/uuid.php');
// Setting up nodes:
CassandraConn::add_node('192.168.1.1', 9160);
CassandraConn::add_node('192.168.1.2', 5000);
// Create a column family object
$users = new CassandraCF('Keyspace1', 'Users'); // ColumnFamily
$super = new CassandraCF('Keyspace1', 'SuperColumn', true); // SuperColumnFamily
// Inserting:
$users->insert('1', array('email' => 'email@correo.com', 'password' => 'test'));
// Querying:
$users->get('1'); // array('email' => 'email@correo.com', 'password' => 'test')
$users->multiget(array('1', '2')); // array('1' => array('email' => 'email@correo.com', 'password' => 'test'))
// Removing:
$users->remove('1'); // removes whole object
$users->remove('1', 'password'); // removes 'password' field
// Other:
$users->get_count('1'); // counts the number of columns in user 1 (in this case 2)
$users->get_range('1', '10'); // gets all users between '1' and '10'
?>

phpcassa

Share Button

Crear thumbs con WordPress

Si antes hablaba de una librería que crea thumbs con PHP, ahora comento cómo hacerlo con WordPress, ya que a veces es necesario subir ficheros cuando WP se utiliza para algo más que un simple blog:

// uploadfile tiene el path del fichero subido
// el cuarto parámetro es para que haga crop
$thumb = image_resize($uploadfile, $width, $height, true); 
$upload = wp_upload_dir();
$thumburl = str_replace($upload['path'], $upload['url'],  $thumb );
Share Button

PHP Thumbnailer: librería para crear thumbs de imágenes

Si hay algo que odio a la hora de desarrollar una aplicación es tener que hacer thumbs de las imágenes, sobre todo para los perfiles: que si el thumb es cuadrado y la imagen rectangular, que si se debe recortar o meter bordes, … PHP Thumbnailer nos facilita enormemente esta tarea:

Hacer resize:

try {
     $thumb = PhpThumbFactory::create('/path/to/image.jpg');
} catch (Exception $e) {
     // error
}
$thumb->resize(100, 100);
$thumb->show();

Hacer resize y crop si es rectangular:

$thumb->adaptiveResize(175, 175);
$thumb->save('/path/to/new_image.jpg');

PHP Thumbnailer

Share Button

Subir y exportar documentos usando Google Docs y PHP

Uno de los problemas con los que nos podemos encontrar es tener un documento en un formato y tener que exportarlo en otro formato. La exportación se puede realizar utilizando Google Docs, quizás un tanto rebuscada la solución, aunque quizás no tanto.

Os paso un script que sube el fichero a Google Docs dentro de una carpeta y acto seguido lo exporta a otro formato, en este caso subo un PPT y lo convierto en PDF (me hubiese encantado que fuera a HTML pero no acepta esa opción).

// Datos de login a la API de Google
$clientlogin_url = "https://www.google.com/accounts/ClientLogin";
$clientlogin_post = array(
    "accountType" => "GOOGLE",
    "Email" => "miemail@gmail.com",
    "Passwd" => "mipassword",
    "service" => "writely",
    "source" => "WPDOCS"
);
 
// Inicializamos el CURL
$curl = curl_init($clientlogin_url);
 
// Obtenemos el string de autenticación
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $clientlogin_post);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($curl);
preg_match("/Auth=([a-z0-9_\-]+)/i", $response, $matches);
$auth = $matches[1];
 
// Cabeceras de autenticación
$headers = array(
    "Authorization: GoogleLogin auth=" . $auth,
    "GData-Version: 3.0",
);
 
// Recuperamos los ficheros y carpetas que tenemos en Google Docs para no crear dos veces la misma carpeta
curl_setopt($curl, CURLOPT_URL, "http://docs.google.com/feeds/default/private/full?showfolders=true");
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_POST, false);
$listado = curl_exec($curl);
$nombre_carpeta = 'WPDOCS';
 
// Si no se ha creado la carpeta, la creamos
if (strpos($listado, '<title>'.$nombre_carpeta.'</title>') === FALSE) {
  // Make the request
  $h = array_merge($headers,array('Content-Type: application/atom+xml'));
  $xml = '<?xml version="1.0" encoding="UTF-8"?><entry xmlns="http://www.w3.org/2005/Atom"><category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/docs/2007#folder"/><title>'.$nombre_carpeta.'</title></entry>';
  curl_setopt($curl, CURLOPT_URL, "http://docs.google.com/feeds/default/private/full");
  curl_setopt($curl, CURLOPT_HTTPHEADER, $h);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $xml);
  curl_setopt($curl, CURLOPT_POST, true);
 
  $response = curl_exec($curl);
  $response = simplexml_load_string($response);
  $id_folder = $response->id;
} else {
  // Recuperamos la ID de la carpeta creada anteriormente
  preg_match("#<title>$nombre_carpeta</title><content type='application/atom\+xml;type=feed' src='([^']+)'#", $listado, $m);
  $id_folder = $m[1];
}
 
// Subimos el PPT
$h = array_merge($headers,array('Content-Type: application/vnd.ms-powerpoint', 'Slug: fichero'));
$filepath='/path/fichero.ppt';
$data=((fread(fopen($filepath, "rb"), filesize($filepath))));
curl_setopt($curl, CURLOPT_URL, "http://docs.google.com/feeds/default/private/full");
curl_setopt($curl, CURLOPT_HTTPHEADER, $h);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_POST, true);
$response = curl_exec($curl);
$response = simplexml_load_string($response);
$id_doc = $response->id;
 
// Limpiamos los IDs de los ficheros devueltos por Google, solo nos interesa del %3A para adelante
preg_match('/%3A(.+)/', $id_doc, $m);
$id_doc = $m[1];
preg_match('/%3A(.+)/', $id_folder, $m);
$id_folder = $m[1];
 
// Lo movemos a la carpeta
$h = array_merge($headers,array('Content-Type: application/atom+xml'));
$data = '<?xml version=\'1.0\' encoding=\'UTF-8\'?><entry xmlns="http://www.w3.org/2005/Atom"><id>https://docs.google.com/feeds/default/private/full/document%3A'.$id_doc.'</id></entry>';
curl_setopt($curl, CURLOPT_URL, "http://docs.google.com/feeds/default/private/full/folder%3A".$id_folder);
curl_setopt($curl, CURLOPT_HTTPHEADER, $h);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_POST, true);
$response = curl_exec($curl);
 
//header('Content-type: text/xml');
//echo $response;
// Parse the response
 
// Exportamos a HTML
curl_setopt($curl, CURLOPT_URL, "http://docs.google.com/feeds/download/presentations/Export?docID=$id_doc&exportFormat=pdf");
curl_setopt($curl, CURLOPT_HTTPHEADER, $h);
curl_setopt($curl, CURLOPT_POST, false);
header('Content-type: application/pdf');
echo curl_exec($curl);
 
curl_close($curl);

Vía / Google Docs API: Client Login with PHP and Curl

Share Button

Librería PHP para Google Buzz

La verdad es que no tengo ni idea del éxito/uso de Google Buzz, dicen que es un fracaso, pero claro, a saber lo que es un fracaso comparado con otras redes sociales (no Twitter o Facebook, claro), por lo que no está mal saber que existe una librería y que te permite trabajar con Google Buzz.

 
// Include the library files
require_once "google-api-php-client/src/apiClient.php";
require_once "google-api-php-client/src/contrib/apiBuzzService.php";
 
// Create the apiClient and Buzz service classes:
$apiClient = new apiClient();
$buzz = new apiBuzzService($apiClient);
 
// Add the OAuth authentication flow to your app:
// If a oauth token was stored in the session, use that- and otherwise go through the oauth dance
session_start();
if (isset($_SESSION['auth_token'])) {
  $apiClient->setAccessToken($_SESSION['auth_token']);
} else {
  // In a real application this would be stored in a database, and not in the session!
  $_SESSION['auth_token'] = $apiClient->authenticate();
}
 
// Make an API call
$activities = $buzz->listActivities('@consumption', '@me');
 
// And echo the returned activities
echo "<pre>Activities:\n" . print_r($activities, true) . "</pre>";

buzz-php-client

Share Button

Acortar URLs mediante goo.gl y PHP

La API de Google para acortar URLs permite acortar URLs, recuperar info del link original y las URLs acortadas de un usuario, aunque para usarlo se necesita crear una clave y dar de alta proyecto.

El resto es fácil, acceso mediante CURL y listo:

    define('GOOGLE_API_KEY', '[insert your key here]');
    define('GOOGLE_ENDPOINT', 'https://www.googleapis.com/urlshortener/v1');
 
    function shortenUrl($longUrl)
    {
        // initialize the cURL connection
        $ch = curl_init(
            sprintf('%s/url?key=%s', GOOGLE_ENDPOINT, GOOGLE_API_KEY)
        );
 
        // tell cURL to return the data rather than outputting it
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 
        // create the data to be encoded into JSON
        $requestData = array(
            'longUrl' => $longUrl
        );
 
        // change the request type to POST
        curl_setopt($ch, CURLOPT_POST, true);
 
        // set the form content type for JSON data
        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
 
        // set the post body to encoded JSON data
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($requestData));
 
        // perform the request
        $result = curl_exec($ch);
        curl_close($ch);
 
        // decode and return the JSON response
        return json_decode($result, true);
    }
 
    $response = shortenUrl('http://phpriot.com');
 
    echo sprintf(
        '%s was shortened to %s',
        $response['longUrl'],
        $response['id']
    );

Shortening URLs for goo.gl with Google’s URL Shortener API

Vía / PHPDeveloper.org

Share Button