<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>voragine.net &#187; Desarrollo web</title>
	<atom:link href="http://voragine.net/archivo/weblogs/feed" rel="self" type="application/rss+xml" />
	<link>http://voragine.net</link>
	<description>Autonomía digital y tecnológica.</description>
	<lastBuildDate>Fri, 04 May 2012 17:37:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Cómo añadir dinámicamente campos a un formulario HTML con jQuery</title>
		<link>http://voragine.net/weblogs/como-anadir-dinamicamente-campos-a-un-formulario-html-con-jquery</link>
		<comments>http://voragine.net/weblogs/como-anadir-dinamicamente-campos-a-un-formulario-html-con-jquery#comments</comments>
		<pubDate>Fri, 30 Mar 2012 08:00:53 +0000</pubDate>
		<dc:creator>skotperez</dc:creator>
				<category><![CDATA[Desarrollo web]]></category>
		<category><![CDATA[form]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://voragine.net/?p=956</guid>
		<description><![CDATA[El siguiente script de jQuery incorpora dos botones a un formulario HTML que permiten añadir y eliminar campos a voluntad. Lo encontré en el recomendable <strong><a title="jQuery – Dynamically Adding Form Elements -- Charlie Griefer's blog" href="http://charlie.griefer.com/blog/2009/09/17/jquery-dynamically-adding-form-elements/">blog de Charlie Griefer</a></strong>. En la página de Charlie se puede probar <a title="Dynamically Adding Form Elements. Demo -- Charlie Griefer Blog" href="http://charlie.griefer.com/blog/jquery-dynamically-adding-form-elements/">una demo</a>.]]></description>
			<content:encoded><![CDATA[<p>El siguiente script de jQuery incorpora dos botones a un formulario HTML que permiten añadir y eliminar campos a voluntad. Lo encontré en el recomendable <strong><a title="jQuery – Dynamically Adding Form Elements -- Charlie Griefer's blog" href="http://charlie.griefer.com/blog/2009/09/17/jquery-dynamically-adding-form-elements/">blog de Charlie Griefer</a></strong>. En la página de Charlie se puede probar <a title="Dynamically Adding Form Elements. Demo -- Charlie Griefer Blog" href="http://charlie.griefer.com/blog/jquery-dynamically-adding-form-elements/">una demo</a>.</p>
<pre class="brush: jscript; title: ; notranslate">
$(document).ready(function() {
  $('#btnDel').attr('disabled','disabled');
  $('#btnAdd').click(function() {
    var num = $('.clonedInput').length; // how many &quot;duplicatable&quot; input fields we currently have
    var newNum = new Number(num + 1); // the numeric ID of the new input field being added

    // create the new element via clone(), and manipulate it's ID using newNum value
    var newElem = $('#input' + num).clone().attr('id', 'Add' + newNum);

    // manipulate the name/id values of the input inside the new element
    newElem.children(':last').attr('id', 'name' + newNum).attr('name', 'name' + newNum);

    // insert the new element after the last &quot;duplicatable&quot; input field
    $('#input' + num).after(newElem);

    // enable the &quot;remove&quot; button
    $('#btnDel').attr('disabled',false);

    // business rule: you can only add 10 names
    if (newNum == 10)
      $('#btnAdd').attr('disabled','disabled');
  });

  $('#btnDel').click(function() {
    var num = $('.clonedInput').length; // how many &quot;duplicatable&quot; input fields we currently have
    $('#input' + num).remove(); // remove the last element

    // enable the &quot;add&quot; button
    $('#btnAdd').attr('disabled',false);

    // if only one element remains, disable the &quot;remove&quot; button
    if (num-1 == 1)
      $('#btnDel').attr('disabled','disabled');
  });

});
</pre>
<p>Y ahora el DOM:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;form id=&quot;testform&quot;&gt;
   &lt;fieldset id=&quot;input1&quot; class=&quot;clonedInput&quot;&gt;
      &lt;label&gt;Name&lt;/label&gt;
      &lt;input type=&quot;text&quot; name=&quot;name1&quot; id=&quot;name1&quot; /&gt;
   &lt;/fieldset&gt;
   &lt;fieldset&gt;
      &lt;label&gt;Need more fields?&lt;/label&gt;
      &lt;inputtype=&quot;button&quot; id=&quot;btnAdd&quot; value=&quot;+&quot; /&gt;
      &lt;input type=&quot;button&quot; id=&quot;btnDel&quot; value=&quot;-&quot; /&gt;
   &lt;/fieldset&gt;
&lt;/form&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://voragine.net/weblogs/como-anadir-dinamicamente-campos-a-un-formulario-html-con-jquery/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo actualizar una cuenta de Twitter mediante PHP y OAuth: aplicación para publicar en el timeline de un usuario</title>
		<link>http://voragine.net/weblogs/como-actualizar-una-cuenta-de-twitter-mediante-php-y-oauth-aplicacion-para-publicar-en-el-timeline-de-un-usuario</link>
		<comments>http://voragine.net/weblogs/como-actualizar-una-cuenta-de-twitter-mediante-php-y-oauth-aplicacion-para-publicar-en-el-timeline-de-un-usuario#comments</comments>
		<pubDate>Thu, 22 Mar 2012 15:16:00 +0000</pubDate>
		<dc:creator>skotperez</dc:creator>
				<category><![CDATA[Desarrollo web]]></category>
		<category><![CDATA[Scripting y programación]]></category>
		<category><![CDATA[cRT]]></category>
		<category><![CDATA[OAuth]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[twitter API]]></category>
		<category><![CDATA[twitteroauth]]></category>

		<guid isPermaLink="false">http://voragine.net/?p=944</guid>
		<description><![CDATA[Para <strong><a title="Actualizar Twitter a través de PHP y OAuth -- Más que WordPress" href="http://www.masquewordpress.com/actualizar-twitter-a-traves-de-php-y-oauth/">actualizar una cuenta de Twitter desde una web externa</a></strong> hay crear una aplicación que utilice el sistema de autentificación OAuth. Para ello hay que registrarla en la <a title="Twitter Developers API" href="https://dev.twitter.com/">página de desarrolladores de Twitter</a>. Para comunicarse con Twitter a través de OAuth se pueden usar varias librerías ya preparadas; en este caso usaremos <strong><a title="Librería twitteroauth -- github.com" href="http://github.com/abraham/twitteroauth">twitteroauth</a></strong> de <a title="Abraham -- github.com" href="http://github.com/abraham">Abraham,</a> que consiste en dos archivos: <code>OAuth.php</code> y <code>twitteroauth.php</code>.]]></description>
			<content:encoded><![CDATA[<p>Para <strong><a title="Actualizar Twitter a través de PHP y OAuth -- Más que WordPress" href="http://www.masquewordpress.com/actualizar-twitter-a-traves-de-php-y-oauth/">actualizar una cuenta de Twitter desde una web cualquiera</a></strong> hay crear una aplicación que utilice el sistema de autentificación OAuth. Para ello hay que registrarla en la <a title="Twitter Developers API" href="https://dev.twitter.com/">página de desarrolladores de Twitter</a>. Para comunicarse con Twitter a través de OAuth se pueden usar varias librerías ya preparadas; en este caso usaremos <strong><a title="Librería twitteroauth -- github.com" href="http://github.com/abraham/twitteroauth">twitteroauth</a></strong> de <a title="Abraham -- github.com" href="http://github.com/abraham">Abraham,</a> que consiste en dos archivos: <code>OAuth.php</code> y <code>twitteroauth.php</code>.</p>
<p>Primero <strong>registramos la aplicación</strong> en la <a title="Applications -- Twitter developers API" href="https://dev.twitter.com/apps">base de datos de Twitter</a>. Es importante configurar el acceso de la aplicación con permisos de lectura y escritura, en la pestaña Settings. Luego generamos las cuatro claves que validarán la aplicación, que luego hay que añadir al código PHP: consumer key, consumer secret, access token y access token secret.</p>
<p>Después, reunimos en un archivo PHP los trozos de código que necesitamos. Incluimos la librería twitteroauth y validamos la aplicación con las cuatro claves que hemos generado:</p>
<pre class="brush: php; title: ; notranslate">
require('twitteroauth.php'); // incluimos la librería para comunicarnos con twitter
define('_CONSUMER_KEY','tuConsumerKey'); // consumer key
define('_CONSUMER_SECRET','tuConsumerSecret'); // consumer secret
define('_OAUTH_TOKEN','tuOAuthToken'); // access token
define('_OAUTH_TOKEN_SECRET','tuOAuthTokenSecret'); // access token secret
</pre>
<p>Creamos una función que realizará la conexión:</p>
<pre class="brush: php; title: ; notranslate">
function getConnectionWithAccessToken() {
  $connection = new TwitterOAuth(_CONSUMER_KEY, _CONSUMER_SECRET,_OAUTH_TOKEN, _OAUTH_TOKEN_SECRET);
  return $connection;
}
</pre>
<p>Ejecutamos la conexión:</p>
<pre class="brush: php; title: ; notranslate">
// Ejecutamos la conexión
$connection = getConnectionWithAccessToken();
</pre>
<p>Publicamos en twitter, utilizando la conexión:</p>
<pre class="brush: php; title: ; notranslate">
//Publicamos el mensaje en twitter
$mensaje = &quot;Publicando un mensaje en una cuenta de Twitter utilizando OAuth.&quot;;
$twitter= $connection-&gt;post('statuses/update', array('status' =&gt; $mensaje) );
</pre>
<p>No es necesario preocuparse por los enlaces incluidos en el mensaje ya que Twitter los acortará convenientemente él solito. Lo que sí que tenemos que tener en cuenta es que <a href="https://dev.twitter.com/discussions/670">si la hora de nuestro servidor está mal configurada obtendremos un error</a> diciéndonos que hay un desfase de tiempo demasiado grande, y el tweet no se publicará:</p>
<pre class="brush: php; title: ; notranslate">
Error Timestamp out of bounds
</pre>
<p>Para detectar éste o cualquier otro error conviene hacer un <code>echo</code> de la variable <code>$twitter</code>, que almacenará los errores en caso de producirse, cuando ejecutemos el archivo PHP.</p>
<p>Más información:</p>
<ul>
<li><a title="Using @abraham's PHP twitteroauth Library -- Twitter Developers API" href="https://dev.twitter.com/docs/auth/oauth/single-user-with-examples#php">Using @abraham&#8217;s PHP twitteroauth Library</a></li>
<li><a title="Actualizar Twitter a través de PHP y OAuth -- Más que WordPress" href="http://www.masquewordpress.com/actualizar-twitter-a-traves-de-php-y-oauth/">Actualizar Twitter a través de PHP y OAuth</a></li>
<li><a title="twitteroauth / DOCUMENTATION -- github.com" href="https://github.com/abraham/twitteroauth/blob/master/DOCUMENTATION">twitteroauth documentation on github</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://voragine.net/weblogs/como-actualizar-una-cuenta-de-twitter-mediante-php-y-oauth-aplicacion-para-publicar-en-el-timeline-de-un-usuario/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo detectar si se está haciendo scroll en una página y cómo cuantificarlo con jQuery</title>
		<link>http://voragine.net/weblogs/como-detectar-si-se-esta-haciendo-scroll-en-una-pagina-y-como-cuantificarlo-con-jquery</link>
		<comments>http://voragine.net/weblogs/como-detectar-si-se-esta-haciendo-scroll-en-una-pagina-y-como-cuantificarlo-con-jquery#comments</comments>
		<pubDate>Wed, 29 Feb 2012 13:17:37 +0000</pubDate>
		<dc:creator>skotperez</dc:creator>
				<category><![CDATA[Desarrollo web]]></category>
		<category><![CDATA[Usabilidad]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[scroll]]></category>
		<category><![CDATA[scrollTop]]></category>

		<guid isPermaLink="false">http://voragine.net/?p=922</guid>
		<description><![CDATA[<a title="Use jQuery to Detect if User has Scrolled to the Bottom or Top of a Page -- DevCurry" href="http://www.devcurry.com/2010/10/use-jquery-to-detect-if-user-has.html">Detectar si se está haciendo scroll en el navegador y poder cuantificarlo</a> —saber la posición vertical de la página en la ventana del navegador— puede ser muy útil, por ejemplo para crear una barra de navegación que permanezca fija (fixed en CSS) y siempre visible. Valga como ejemplo, la <strong><a title="Thinkcommons -- Ambient Intelligent Network" href="http://thinkcommons.org/">página del proyecto Thinkcommons</a></strong> de <a title="Blog personal de Domenico Di Siena" href="http://urbanohumano.org">Domenico Di Siena</a>, en el que estoy colaborando. Esto lo podemos conseguir con <a title=".scrollTop() -- jQuery API" href="http://api.jquery.com/scrollTop/">la función <code>.scrollTop()</code> de jQuery</a>, que nos devuelve la altura en píxeles que ha quedado oculta por el borde superior de la ventana del navegador.]]></description>
			<content:encoded><![CDATA[<p><a title="Use jQuery to Detect if User has Scrolled to the Bottom or Top of a Page -- DevCurry" href="http://www.devcurry.com/2010/10/use-jquery-to-detect-if-user-has.html">Detectar si se está haciendo scroll en el navegador y poder cuantificarlo</a> —saber la posición vertical de la página en la ventana del navegador— puede ser muy útil, por ejemplo para crear una barra de navegación que permanezca fija (fixed en CSS) y siempre visible. Valga como ejemplo, la <strong><a title="Thinkcommons -- Ambient Intelligent Network" href="http://thinkcommons.org/">página del proyecto Thinkcommons</a></strong> de <a title="Blog personal de Domenico Di Siena" href="http://urbanohumano.org">Domenico Di Siena</a>, en el que estoy colaborando. Esto lo podemos conseguir con <a title=".scrollTop() -- jQuery API" href="http://api.jquery.com/scrollTop/">la función <code>.scrollTop()</code> de jQuery</a>, que nos devuelve la altura en píxeles que ha quedado oculta por el borde superior de la ventana del navegador.</p>
<p>La siguiente función de jQuery permite saber cuándo un elemento del DOM está en la parte superior de la ventana del navegador para, en ese momento, cambiarle las propiedades de estilo necesarias y que permanezca siempre visible. Básicamente asocia <code>.scrollTop()</code> al método <code><a title=".scroll() -- jQuery API" href="http://api.jquery.com/scroll/">.scroll()</a></code>:</p>
<pre class="brush: jscript; title: ; notranslate">
$(function () {
  var $win = $(window);
  // definir mediente $pos la altura en píxeles desde el borde superior de la ventana del navegador y el elemento
  var $pos = 140;
  $win.scroll(function () {
     if ($win.scrollTop()        $('.menu').removeClass('fijar');
     else {
       $('.menu').addClass('fijar');
     }
   });
});
</pre>
<p>Esto lo podemos aplicar a un elemento del DOM con la clase <code>menu</code>:</p>
<pre class="brush: xml; title: ; notranslate">&lt;/pre&gt;
&lt;ul class=&quot;menu fijar&quot;&gt;
	&lt;li&gt;Item 1&lt;/li&gt;
	&lt;li&gt;Item 2&lt;/li&gt;
	&lt;li&gt;Item 3&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;
</pre>
<p>que cuando se encuentre en la parte superior de la ventana adquirira la clase <code>fijar</code>:</p>
<pre class="brush: xml; title: ; notranslate">&lt;/pre&gt;
&lt;ul class=&quot;menu fijar&quot;&gt;
	&lt;li&gt;Item 1&lt;/li&gt;
	&lt;li&gt;Item 2&lt;/li&gt;
	&lt;li&gt;Item 3&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;
</pre>
<p>Los estilos CSS que darán propiedades al elemento los podemos definir de la siguiente manera:</p>
<pre class="brush: css; title: ; notranslate">
.menu {
  position: absolute;
  top: 140px;
}
.fijar {
  position: fixed !important;
  top: 0 !important;
  z-index: 100;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://voragine.net/weblogs/como-detectar-si-se-esta-haciendo-scroll-en-una-pagina-y-como-cuantificarlo-con-jquery/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cuidado con los espacios en blanco al usar getimagesize: error failed to open stream</title>
		<link>http://voragine.net/weblogs/cuidado-con-los-espacios-en-blanco-al-usar-getimagesize-error-failed-to-open-stream</link>
		<comments>http://voragine.net/weblogs/cuidado-con-los-espacios-en-blanco-al-usar-getimagesize-error-failed-to-open-stream#comments</comments>
		<pubDate>Wed, 08 Feb 2012 15:49:04 +0000</pubDate>
		<dc:creator>skotperez</dc:creator>
				<category><![CDATA[Desarrollo web]]></category>
		<category><![CDATA[getsizeimage]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[rtrim]]></category>

		<guid isPermaLink="false">http://voragine.net/?p=889</guid>
		<description><![CDATA[La función <strong><a title="getimagesize -- Php.net" href="http://php.net/manual/es/function.getimagesize.php">getsizeimage</a></strong> de PHP devuelve una matriz con información sobre una imagen: sus dimensiones, el tipo de imagen... Muy útil para hacer redimensiones o saber si está dentro de los límites de tamaño que queremos manejar en nuestra página, por ejemplo. La tenemos que alimentar con la ruta hasta el archivo, incluyendo el nombre completo.

Para usarla sólo hay que tener presente que el nombre del archivo de imagen tiene que ser una cadena <strong>sin espacios al principio o al final</strong>.]]></description>
			<content:encoded><![CDATA[<p>La función <strong><a title="getimagesize -- Php.net" href="http://php.net/manual/es/function.getimagesize.php">getsizeimage</a></strong> de PHP devuelve una matriz con información sobre una imagen: sus dimensiones, el tipo de imagen&#8230; Muy útil para hacer redimensiones o saber si está dentro de los límites de tamaño que queremos manejar en nuestra página, por ejemplo. La tenemos que alimentar con la ruta hasta el archivo, incluyendo el nombre completo.</p>
<p>El uso básico es el siguiente:</p>
<pre class="brush: php; title: ; notranslate">
$img_data = getimagesize($image);
</pre>
<p>Para usarla sólo hay que tener presente que el nombre del archivo de imagen tiene que ser una cadena <strong>sin espacios al principio o al final</strong>; de no ser así, PHP nos devolverá el siguiente error:</p>
<pre class="brush: xml; title: ; notranslate">
Warning: getimagesize(imagen.jpg ) [function.getimagesize]: failed to open stream: No such file or directory...
</pre>
<p>Con un poco de atención, algo que no he tenido los dos últimos días, se puede detectar que en el mensaje de error, dentro del paréntesis, tras el nombre de la imagen hay un espacio. Esto es lo que está provocando que no encuentre la imagen.</p>
<p>Para evitar que los espacios nos vuelvan locos podemos usar <strong><a title="rtrim -- Php.net" href="http://www.php.net/manual/en/function.rtrim.php">rtrim</a></strong>, que elimina espacios en blanco al principio y al final de una cadena antes de procesarla:</p>
<pre class="brush: php; title: ; notranslate">
$img_data = getimagesize(rtrim($image));
</pre>
<p>Lo encontré buceando en el <a title="Getimagesize loop only checks first image? -- sitepoint.com" href="http://www.sitepoint.com/forums/showthread.php?441905-Getimagesize-loop-only-checks-first-image">código de sitepoint</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://voragine.net/weblogs/cuidado-con-los-espacios-en-blanco-al-usar-getimagesize-error-failed-to-open-stream/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo ejecutar PHP periódicamente con cron en un servidor Linux</title>
		<link>http://voragine.net/weblogs/como-ejecutar-php-periodicamente-con-cron-en-un-servidor-linux</link>
		<comments>http://voragine.net/weblogs/como-ejecutar-php-periodicamente-con-cron-en-un-servidor-linux#comments</comments>
		<pubDate>Sat, 31 Dec 2011 07:00:23 +0000</pubDate>
		<dc:creator>skotperez</dc:creator>
				<category><![CDATA[Desarrollo web]]></category>
		<category><![CDATA[GNU/Linux]]></category>
		<category><![CDATA[Scripting y programación]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[cron]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://voragine.net/?p=866</guid>
		<description><![CDATA[Primero tenemos que tener la posibilidad de <strong><a title="Usando PHP desde la línea de comandos -- php.net" href="http://php.net/manual/es/features.commandline.php">ejecutar un script PHP desde la línea de comandos</a></strong>, o en su defecto <a title="Ejecutar scripts PHP automáticamente desde el cron con CURL -- programacion.com" href="http://www.programacion.com/articulo/ejecutar_scripts_php_automaticamente_desde_el_cron_con_curl_302">ejecutarlo con curl</a>; en este tutorial lo haremos ejecutando el PHP directamente en la línea de comandos sin curl. Luego tenemos que generar el archivo PHP, y un script sh que ejecute el script PHP. Por último, <strong><a title="MANUAL BÁSICO DE CRON -- linuxtotal.com.mx" href="http://www.linuxtotal.com.mx/index.php?cont=info_admon_006">configuraremos cron para que ejecute el script de bash con la periodicidad que necesitemos</a></strong>.]]></description>
			<content:encoded><![CDATA[<p>Primero tenemos que tener la posibilidad de <strong><a title="Usando PHP desde la línea de comandos -- php.net" href="http://php.net/manual/es/features.commandline.php">ejecutar un script PHP desde la línea de comandos</a></strong>, o en su defecto <a title="Ejecutar scripts PHP automáticamente desde el cron con CURL -- programacion.com" href="http://www.programacion.com/articulo/ejecutar_scripts_php_automaticamente_desde_el_cron_con_curl_302">ejecutarlo con curl</a>; en este tutorial lo haremos ejecutando el PHP directamente en la línea de comandos sin curl. Luego tenemos que generar el archivo PHP, y un script sh que ejecute el script PHP. Por último, <strong><a title="MANUAL BÁSICO DE CRON -- linuxtotal.com.mx" href="http://www.linuxtotal.com.mx/index.php?cont=info_admon_006">configuraremos cron para que ejecute el script de bash con la periodicidad que necesitemos</a></strong>.</p>
<p>Para ejecutar un script PHP en la línea de comandos necesitamos tener instalado el paquete <code>php5-cli</code>, como root.</p>
<pre class="brush: bash; title: ; notranslate">apt-get install php5-cli</pre>
<p>La sintaxis para ejecutar un script PHP es la siguiente:</p>
<pre class="brush: bash; title: ; notranslate">php file.php</pre>
<p>Generamos un script PHP mínimo, <a title="PHP to save data to a text file -- http://board.flashkit.com" href="http://board.flashkit.com/board/showthread.php?t=491680">que escribirá una línea en un archivo de texto plano cada vez que se ejecute</a>, y lo llamamos por ejemplo <code>test.cron.php</code>; el archivo se alojará en el mismo directorio que los scripts.</p>
<pre class="brush: php; title: ; notranslate">$time = date(&quot;G:i:s&quot;);
$entry = &quot;Información guardada a las $time.\n&quot;;
$file = &quot;/var/www/testdir/test.cron.txt&quot;;
$open = fopen($file,&quot;a&quot;);

if ( $open ) {
	fwrite($open,$entry);
	fclose($open);
}</pre>
<p>Para que al ejecutar el script con cron no nos dé el error <code>Could not open input file: test.cron.php</code>, es recomendable especificar la ruta completa al archivo PHP. Si el error que obtenemos está relacionado con <code>open_basedir restriction</code> tenemos que definir la variable <code>open_basedir</code> en el archivo <code><a title="Descripción de las directivas del núcleo de php.ini -- php.net" href="http://php.net/manual/es/ini.core.php">/etc/php5/cli/php.ini</a></code> y asignarle como valor la ruta del directorio donde se encuentre el script PHP, como root, <a title="open_basedir restriction in effect -- forosdelweb.com" href="http://www.linuxtotal.com.mx/index.php?cont=info_admon_006">importante el punto final</a>:</p>
<pre class="brush: bash; title: ; notranslate">open_basedir = /var/www/testdir/.</pre>
<p>Luego reiniciamos el servidor apache, como root:</p>
<pre class="brush: bash; title: ; notranslate">/etc/init.d/apache restart</pre>
<p>Creamos ahora un script de bash que ejecute el script PHP; lo llamamos por ejemplo <code>test.cron.sh</code>:</p>
<pre class="brush: bash; title: ; notranslate">#!/bin/sh
php /var/www/testdir/test.cron.php</pre>
<p>Es importante la primera línea que le dice al sistema el tipo de shell que debe usar para ejecutar el script. La shell tiene que ser la misma que almacena la variable <code>SHELL</code> del archivo <code>/etc/crontab</code>, <code>/bin/sh</code> en mi caso.</p>
<p>Por último, <strong><a title="MANUAL BÁSICO DE CRON -- linuxtotal.com.mx" href="http://www.linuxtotal.com.mx/index.php?cont=info_admon_006">configuramos cron</a></strong>, tras asegurarnos de que el demonio crond está corriendo. Básicamente necesitamos decirle a cron qué script queremos ejecutar y con qué periodicidad. Podemos hacerlo editando el archivo <code>/etc/crontab</code>, añadiéndole la siguiente línea, a continuación de las reglas ya existentes, como root:</p>
<pre class="brush: bash; title: ; notranslate">*/15 * * * * usuario /var/www/testdir/./test.cron.sh</pre>
<p>En este caso, el script <code>/var/www/testdir/./test.cron.sh</code> se ejecutará cada quince minutos. Es importante que el <code>usuario</code> tenga suficientes permisos para leer y ejecutar el script.</p>
]]></content:encoded>
			<wfw:commentRss>http://voragine.net/weblogs/como-ejecutar-php-periodicamente-con-cron-en-un-servidor-linux/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo transformar el formato de un flujo RSS, mediante DOM, para poder usarlo libremente con PHP</title>
		<link>http://voragine.net/weblogs/como-transformar-el-formato-de-un-flujo-rss-mediante-dom-para-poder-usarlo-libremente-con-php</link>
		<comments>http://voragine.net/weblogs/como-transformar-el-formato-de-un-flujo-rss-mediante-dom-para-poder-usarlo-libremente-con-php#comments</comments>
		<pubDate>Wed, 14 Dec 2011 18:38:49 +0000</pubDate>
		<dc:creator>skotperez</dc:creator>
				<category><![CDATA[Desarrollo web]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[RSS]]></category>

		<guid isPermaLink="false">http://voragine.net/?p=854</guid>
		<description><![CDATA[RSS o Really Simple Syndication es una simplificación de XML. Mediante DOM (Document Object Model) podemos transformar cualquier flujo XML en una matriz multidimensional con la que podremos operar fácilmente en PHP.]]></description>
			<content:encoded><![CDATA[<p>RSS o Really Simple Syndication es una simplificación de XML. Mediante DOM (Document Object Model) podemos transformar cualquier flujo XML en una matriz multidimensional con la que podremos operar fácilmente en PHP.</p>
<p>Tomemos como ejemplo un XML de los últimos tweets de un usuario de Twitter, <a title="skotperez en twitter" href="http://twitter.com/skotperez">@skotperez</a> en este caso. Podemos <a title="How to follow a Twitter account feed using RSS Reader in New Twitter -- God, Your Book Is Great !!" href="http://saravananthirumuruganathan.wordpress.com/2011/05/29/how-to-follow-a-twitter-account-feed-using-rss-reader-in-new-twitter/">extraer esta información gracias a la API de Twitter</a>.</p>
<p><code><a href="https://api.twitter.com/1/statuses/user_timeline.rss?screen_name=skotperez">https://api.twitter.com/1/statuses/user_timeline.rss?screen_name=skotperez</a></code></p>
<p>Una vez que tenemos el feed lo <strong><a title="How to parse RSS feeds with PHP -- Software 51" href="http://www.softarea51.com/tutorials/parse_rss_with_php.html">podemos manipular con DOM y almacenar el resultado en una variable</a></strong>, <code>$arrFeeds</code> en este caso:</p>
<pre class="brush: php; title: ; notranslate">
$feed_url = &quot;https://api.twitter.com/1/statuses/user_timeline.rss?screen_name=skotperez&quot;;
$doc = new DOMDocument();
$doc-&gt;load($feed_url);
$arrFeeds = array();
foreach ($doc-&gt;getElementsByTagName('item') as $node) {
  $itemRSS = array (
    'title' =&gt; $node-&gt;getElementsByTagName('title')-&gt;item(0)-&gt;nodeValue,
    'desc' =&gt; $node-&gt;getElementsByTagName('description')-&gt;item(0)-&gt;nodeValue,
    'link' =&gt; $node-&gt;getElementsByTagName('link')-&gt;item(0)-&gt;nodeValue,
    'date' =&gt; $node-&gt;getElementsByTagName('pubDate')-&gt;item(0)-&gt;nodeValue
  );
  array_push($arrFeeds, $itemRSS);
}
</pre>
<p>Luego podemos hacer correr un loop a lo largo de los elementos de la matriz para obtener la información que queramos:</p>
<pre class="brush: php; title: ; notranslate">
foreach ( $arrFeeds as $tw ) {
  echo $tw['date'];
  echo &quot;&lt;br /&gt;&quot;;
  echo $tw['desc'];
  echo &quot;&lt;br /&gt;&quot;;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://voragine.net/weblogs/como-transformar-el-formato-de-un-flujo-rss-mediante-dom-para-poder-usarlo-libremente-con-php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo centrar un elemento exactamente en el centro, con CSS</title>
		<link>http://voragine.net/weblogs/como-centrar-un-elemento-exactamente-en-el-centro-con-css</link>
		<comments>http://voragine.net/weblogs/como-centrar-un-elemento-exactamente-en-el-centro-con-css#comments</comments>
		<pubDate>Tue, 22 Nov 2011 07:00:07 +0000</pubDate>
		<dc:creator>skotperez</dc:creator>
				<category><![CDATA[Breves]]></category>
		<category><![CDATA[Desarrollo web]]></category>
		<category><![CDATA[CSS]]></category>

		<guid isPermaLink="false">http://voragine.net/?p=841</guid>
		<description><![CDATA[Para centrar un elemento de unas dimensiones concretas, por ejemplo de 100px de alto y 200px de ancho, en el centro de la página con CSS podemos usar los siguientes atributos de CSS.]]></description>
			<content:encoded><![CDATA[<p>Para <strong><a title="Quick CSS Trick: How To Center an Object Exactly In The Center -- CSS Trick" href="http://css-tricks.com/320-quick-css-trick-how-to-center-an-object-exactly-in-the-center/">centrar un elemento de unas dimensiones concretas</a></strong>, por ejemplo de 100px de alto y 200px de ancho, en el centro de la página podemos usar los siguientes atributos de CSS:</p>
<pre class="brush: css; title: ; notranslate">
.centered {
  position: fixed;
  top: 50%;
  left: 50%;
  margin-top: -50px;
  margin-left: -100px;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://voragine.net/weblogs/como-centrar-un-elemento-exactamente-en-el-centro-con-css/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Galería mínima para imágenes, vídeos o textos, en jQuery</title>
		<link>http://voragine.net/weblogs/galeria-minima-para-imagenes-videos-o-textos-en-jquery</link>
		<comments>http://voragine.net/weblogs/galeria-minima-para-imagenes-videos-o-textos-en-jquery#comments</comments>
		<pubDate>Mon, 21 Nov 2011 18:39:06 +0000</pubDate>
		<dc:creator>skotperez</dc:creator>
				<category><![CDATA[Desarrollo web]]></category>
		<category><![CDATA[fadeIn]]></category>
		<category><![CDATA[fadeOut]]></category>
		<category><![CDATA[galerías de imagenes]]></category>
		<category><![CDATA[jQuery]]></category>

		<guid isPermaLink="false">http://voragine.net/?p=836</guid>
		<description><![CDATA[El siguiente script de jQuery añade una galería mínima, muy sencilla, que permite paginar contenido e ir accediendo a él mediante unas flechas de anterior y siguiente, con transición fadeIn-fadeOut.]]></description>
			<content:encoded><![CDATA[<p>El siguiente script de jQuery añade una galería mínima, muy sencilla, que permite paginar contenido e ir accediendo a él mediante unas flechas de anterior y siguiente, con transición fadeIn-fadeOut.</p>
<p>El DOM debe ser algo como lo que sigue:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;div id=&quot;flus&quot;&gt;

  &lt;div class=&quot;part&quot;&gt;
   &lt;img src=&quot;http://url.de/la-imagen.png&quot; alt=&quot;Descripción de la imagen&quot; /&gt;
  &lt;/div&gt;&lt;!-- end .part --&gt;

  &lt;div class=&quot;part&quot;&gt;
   &lt;img src=&quot;http://url.de/la-imagen.png&quot; alt=&quot;Descripción de la imagen&quot; /&gt;
  &lt;/div&gt;&lt;!-- end .part --&gt;

  &lt;div class=&quot;part&quot;&gt;
   &lt;img src=&quot;http://url.de/la-imagen.png&quot; alt=&quot;Descripción de la imagen&quot; /&gt;
  &lt;/div&gt;&lt;!-- end .part --&gt;

&lt;/div&gt;&lt;!-- end #flus --&gt;
</pre>
<p>Ahora el script:</p>
<pre class="brush: jscript; title: ; notranslate">
// minimum jQuery gallery
$(document).ready(function(){
        $('#flus div.part').hide();
        $('#flus div.part:first').show().addClass('visto');
        var $curr = $('.visto');
        $('#flus').append('&lt;div class=&quot;flus-flechas&quot;&gt;&lt;span class=&quot;flus-flecha&quot; id=&quot;flus-prev&quot; title=&quot;P&amp;aacute;gina anterior&quot;&gt;&amp;laquo;&lt;/span&gt;&lt;span class=&quot;flus-flecha&quot; id=&quot;flus-next&quot; title=&quot;P&amp;aacute;gina siguiente&quot;&gt;&amp;raquo;&lt;/span&gt;&lt;/div&gt;');
        $('#flus-prev').click(function(){
                if ( $('#flus div.part:first').hasClass('visto') ) {
                } else {
                        $curr = $curr.prev();
                        $('.visto').fadeOut('100').removeClass('visto');
                        $curr.fadeIn('600').addClass('visto');
                }
        });
        $('#flus-next').click(function(){
                if ( $('#flus div.part:last').hasClass('visto') ) {
                } else {
                        $curr = $curr.next();
                        $('.visto').fadeOut('100').removeClass('visto');
                        $curr.fadeIn('600').addClass('visto');
                }
        });
});
</pre>
]]></content:encoded>
			<wfw:commentRss>http://voragine.net/weblogs/galeria-minima-para-imagenes-videos-o-textos-en-jquery/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo obtener el thumbnail y otros datos de vídeos de Youtube</title>
		<link>http://voragine.net/weblogs/como-obtener-el-thumbnail-y-otros-datos-de-videos-de-youtube</link>
		<comments>http://voragine.net/weblogs/como-obtener-el-thumbnail-y-otros-datos-de-videos-de-youtube#comments</comments>
		<pubDate>Tue, 01 Nov 2011 16:54:36 +0000</pubDate>
		<dc:creator>skotperez</dc:creator>
				<category><![CDATA[Desarrollo web]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[youtube]]></category>

		<guid isPermaLink="false">http://voragine.net/?p=802</guid>
		<description><![CDATA[La <a title="Developer Tools -- Youtube" href="http://www.youtube.com/dev">API de Youtube</a> es bastante más farragosa que la de Vimeo; si para <a title="Cómo obtener el thumbnail y otros datos de vídeos de Vimeo, usando su API -- voragine.net" href="http://voragine.net/weblogs/como-obtener-el-thumbnail-y-otros-datos-de-videos-de-vimeo-usando-su-api">obtener datos de un vídeo de Vimeo</a> utilizábamos su API, en el caso de Youtube no merece la pena. En las FAQ de la propia página de Youtube sugieren métodos que nada tienen que ver con extraer datos de la página, como por ejemplo para <a title="YouTube en tu sitio -- Youtube" href="http://www.youtube.com/youtubeonyoursite">conocer las dimensiones de un vídeo</a>.]]></description>
			<content:encoded><![CDATA[<p>La <a title="Developer Tools -- Youtube" href="http://www.youtube.com/dev">API de Youtube</a> es bastante más farragosa que la de Vimeo; si para <a title="Cómo obtener el thumbnail y otros datos de vídeos de Vimeo, usando su API -- voragine.net" href="http://voragine.net/weblogs/como-obtener-el-thumbnail-y-otros-datos-de-videos-de-vimeo-usando-su-api">obtener datos de un vídeo de Vimeo</a> utilizábamos su API, en el caso de Youtube no merece la pena. En las FAQ de la propia página de Youtube sugieren métodos que nada tienen que ver con extraer datos de la página, como por ejemplo para <a title="YouTube en tu sitio -- Youtube" href="http://www.youtube.com/youtubeonyoursite">conocer las dimensiones de un vídeo</a>.</p>
<p>Así que para <strong><a title="How to grab thumbnails for youtube and google video -- scottklarr.com" href="http://www.scottklarr.com/topic/415/how-to-grab-thumbnails-for-youtube-and-google-video/">utilizar el thumbnail de un vídeo de Youtube</a></strong> lo único que tenemos que hacer es hacer una petición al servidor que los aloja, con el identificador del vídeo:</p>
<pre class="brush: php; title: ; notranslate">
$video_id = AtiYuWFXC1g;
// thumb de alta calidad
$video_thumb_hq = &quot;http://img.youtube.com/vi/$video_id/hqdefault.jpg&quot;;
// thumb de calidad baja
$video_thumb = &quot;http://img.youtube.com/vi/$video_id/default.jpg&quot;;
$video_w = &quot;500&quot;; // definimos la que nos interese
$video_h = $video_w * 0.8235;
</pre>
<p>Con estos datos podemos obtener la miniatura en nuestra página:</p>
<pre class="brush: php; title: ; notranslate">
$video_out = &quot;&lt;/pre&gt;
&lt;img style=&quot;width: 125px;&quot; src=&quot;$video_thumb_hq&quot; alt=&quot;$video_title&quot; /&gt;
&lt;pre&gt;
&quot;;
echo $video_out;
</pre>
<p>Y el vídeo también:</p>
<pre class="brush: php; title: ; notranslate">
$video_codigo = &quot;&lt;/pre&gt;
&lt;iframe src=&quot;http://www.youtube.com/embed/$video_id&quot; frameborder=&quot;0&quot; width=&quot;$video_w&quot; height=&quot;$video_h&quot;&gt;&lt;/iframe&gt;
&lt;pre&gt;&quot;;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://voragine.net/weblogs/como-obtener-el-thumbnail-y-otros-datos-de-videos-de-youtube/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cómo obtener el thumbnail y otros datos de vídeos de Vimeo, usando su API</title>
		<link>http://voragine.net/weblogs/como-obtener-el-thumbnail-y-otros-datos-de-videos-de-vimeo-usando-su-api</link>
		<comments>http://voragine.net/weblogs/como-obtener-el-thumbnail-y-otros-datos-de-videos-de-vimeo-usando-su-api#comments</comments>
		<pubDate>Mon, 31 Oct 2011 12:46:22 +0000</pubDate>
		<dc:creator>skotperez</dc:creator>
				<category><![CDATA[Desarrollo web]]></category>
		<category><![CDATA[unserialize]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[vimeo]]></category>
		<category><![CDATA[vimeo API]]></category>
		<category><![CDATA[vimeo thumbnail]]></category>

		<guid isPermaLink="false">http://voragine.net/?p=797</guid>
		<description><![CDATA[Vimeo tiene una API realmente ágil y sencilla. Mediante una petición vía URL se obtienen todos los datos relacionados con un vídeo, pudiendo definir el formato de estos datos. Tal como se explica en la <strong><a title="Developers / Simple API -- vimeo.com" href="http://vimeo.com/api/docs/simple-api">API de Vimeo</a></strong>.]]></description>
			<content:encoded><![CDATA[<p>Vimeo tiene una API realmente ágil y sencilla. Mediante una petición vía URL se obtienen todos los datos relacionados con un vídeo, pudiendo definir el formato de estos datos. Tal como se explica en la <strong><a title="Developers / Simple API -- vimeo.com" href="http://vimeo.com/api/docs/simple-api">API de Vimeo</a></strong>:</p>
<blockquote><p><code>http://vimeo.com/api/v2/video/<strong>video_id</strong>.<strong>output</strong></code><br />
<strong><code>video_id</code></strong> The ID of the video you want information for.<br />
<strong><code>output</code></strong> Specify the output type. We currently offer JSON, PHP, and XML formats.</p></blockquote>
<p>La opción de salida PHP nos permite tener todos los datos del vídeo en una matriz para usarlos a voluntad, pero antes <a title="Get img thumbnails from Vimeo? -- Stackoverflow" href="http://stackoverflow.com/questions/1361149/get-img-thumbnails-from-vimeo">debemos aplicarles el filtro unserialize()</a>:</p>
<pre class="brush: php; title: ; notranslate">
$video_id = 8241516;
$video_info = unserialize(file_get_contents(&quot;http://vimeo.com/api/v2/video/$video_id.php&quot;));
$video_thumb = $video_info[0]['thumbnail_medium'];
$video_title = $video_info[0]['title'];
$video_w = $video_info[0]['width'];
$video_h = $video_info[0]['height'];
$video_url = $video_info[0]['video_url'];
</pre>
<p>Con estos datos podemos obtener la minuatura con un enlace al vídeo:</p>
<pre class="brush: php; title: ; notranslate">
$video_out = &quot;
&lt;a href='$video_url' title='$video_title'&gt;&lt;img style='width: 125px;' src='$video_thumb' alt='$video_title' /&gt;&lt;/a&gt;
&quot;;
echo $video_out;
</pre>
<p>O embeber el vídeo:</p>
<pre class="brush: php; title: ; notranslate">
$video_codigo = &quot;&lt;iframe src='http://player.vimeo.com/video/$video_id?title=0&amp;amp;byline=0&amp;amp;portrait=0&amp;amp;color=ffffff' width='$video_w' height='$video_h' frameborder='0' webkitAllowFullScreen allowFullScreen&gt;&lt;/iframe&gt;&quot;;
echo $video_codigo;
</pre>
<p>La API permite obtener datos también de los usuarios, hacer listas de reproducción. Bien sencillo.</p>
]]></content:encoded>
			<wfw:commentRss>http://voragine.net/weblogs/como-obtener-el-thumbnail-y-otros-datos-de-videos-de-vimeo-usando-su-api/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

