BuddyPress vs Drupal Commons: crea tu red social con software libre

Creo que alguna vez comenté por aquí que estoy trabajando en el desarrollo de módulos para la red social PHPFox. No es que me convenza mucho este cms para la creación de redes sociales, la verdad, pero es cosa de la empresa. En todo caso, creo que PHPFox tiene una documentación que en el mejor de los casos es chapucera y en el peor inexistente, una comunidad profundamente inactiva y mercantilizada y un grave problema de rendimiento y escalabilidad. Y además hay que pagar licencia.

Por eso dediqué unos días a buscar opciones libres para crear una red social, no porque a mi empresa le interese (que de momento parece que están muy contentos con Fox) sino por mera curiosidad, y tal vez para montar alguna algún día, pero es sólo una chorrada que me ronda la cabeza.

A lo que íbamos, ¿qué dos opciones libres suenan con más fuerza? Pues BuddyPress y Drupal Commons. Ambos no son un CMS propiamente dicho, sino extensiones para otros CMS que nos dan la funcionalidad de red social

BuddyPress, como te puedes imaginar, está desarrollado para WordPress. Su instalación es simple: instalas WordPress ( a poder ser, la última versión), subir el plugin al servidor e instalarlo desde el menú de instalar plugins. Total, que en 10 minutos tienes montado todo en tu servidor.

Drupal Commons, evidentemente, es un plugin para Drupal. Su instalación es todavía más sencilla: sólo debes seleccionar el perfil Drupal Commons durante la instalación de Drupal, y listo.

En cuanto a funcionalidades, BuddyPress es menos completo que Commons. El plugin de wordpress incluye un stream de actividades de los usuarios, perfiles extendidos, posibilidad de conectar con amigos, posibilidad de crear grupos extensibles, mensajes privados, foros de discusión y todas las fucionalidades de WordPress para crear blogs. Lo básico para crear una comunidad.

Commons por su parte viene de serie más completo: los perfiles de usuario incluyen más variables, es capaz de crear automáticamente grupos respecto a la información del perfil, incluye foros de discusión, blogs (eso sí, en este caso menos potentes que los de wordpress), creación y gestión de eventos, creación de wikis, administración de documentos, integración con RSS, noticias, mayor control de la privacidad, editor WYSIWYG para los textos, estadísticas de la comunidad…

Bueno, parece que ahí gana Commons ¿o no? Piénsalo bien, más funcionalidades no significa mejor. No quiero decir que Commons por abarcar mucho apriete poco, no, simplemente que es posible que en tu comunidad no necesites todas las funcionalidades que Drupal Commons trae por defecto. Y que no vengan por defecto en BuddyPress no significa que no existan para este, sólo que las tienes que instalar aparte.

En cuanto a diseño, el que incluye por defecto BuddyPress me parece más atractivo, pero ambos pueden ser modificados y personalizados, ya sea a través de la edición manual del css, a través de simples menús de personalización o adquiriendo alguna plantilla (las hay gratis y de pago). En todo caso, para gente que no sepa CSS Drupal Commons es más cómodo de personalizar.

Al ser software libre ambos tienen una amplia comunidad por detrás: Commons está apoyado y mantenido por Acquia, los cuales además de permitirte la descarga gratuita del plugin también ofertan de forma comercial hosting y mantenimiento para tu red. Commons tiene un API que te permitirá desarrollar módulos para extender su funcionamiento, además de tener acceso a miles de módulos. Con BuddyPress tienes menos módulos específicos, pero con todo dispones de todos los módulos de Worpress para añadir.

No voy a decir que uno sea peor que el otro. Creo que para un usuario avanzado BuddyPress es más flexible, y para uno novato Commons, aunque más grande, puede ser más fácil de gestionar al no tener que andar instalando plugins. En todo caso, a vosotros corresponde decidir. Yo todavía tengo que hacer más testeos caseros con ambos, pero ya tengo un par de ideas rondando la cefa.

Dotcom está de vuelta: llega MEGA

Aunque Kim Dotcom no es un personaje al tenga especial cariño hay que destacar que la llegada de Mega es una de las noticias tecnológicas de 2013.

Y es que por mal que me caiga el tío también pienso que el cierre de Megaupload fue un atropello a la libertad para la distribución de contenidos on-line. Una guerra sobre el control de contenidos de la que ya he hablado y que no viene al caso en esta entrada.

Siguiendo con Mega, el primer día ha sido todo un éxito: 250000 usuarios en pocas horas, más de un millón registrados el primer día y los servidores casi colapsados. Y eso que muchos no tienen claro el funcionamiento del nuevo servicio. Y es que Mega no es Megaupload, el nuevo proyecto de Dotcom tiene más que ver con los servicios de almacenamiento cloud como Drive o Dropbox que con su antigua página. Usarla para compartir archivos de forma masiva se tornará más complejo, dado que toda la información estará encriptada, y sólo el usuario tendrá la contraseña. Con esto no sólo consigue dar mayor seguridad a su servicio, sino que también logra descargase de responsabilidades, ya que de esta forma Mega nunca sabe qué ha almacenado el usuario. Una inteligente jugada para evitar problemas con la ley estadounidense como los que tuvo Megaupload.

El problema es que para compartir material el que lo haga deberá publicar su contraseña. Todavía no me he hecho cuenta para probar el servicio, pero por lo que he leído ofrecen 50 GB para los usuarios con cuenta gratuita, por lo que parece una opción interesante para competir con los servicios de almacenamiento más populares.

Crear un web service RESTful con PHP

Ya que ayer hablaba de crear un web service con SOAP hoy toca complementar la información creando un web service REST. Esto nos permitirá crear lo que podríamos llamar una RESTful API.

En este caso nos vamos a servir del framework Slim y de la librería NotORM para el acceso a la base de datos.

Lo primero que haremos será crear una suerte de Hello World con Slim, para probar su funcionamiento

<?php
require "Slim/Slim.php";

// creamos una nueva instancia de Slim
$ejemplo = new Slim();

// agregamos una nueva ruta y un código
$ejemplo->get("/", function () {
    echo "<h1>Ejemplo</h1>";
});

// corremos la aplicación
$ejemplo->run();

Vale, ejemplo simplón de cómo usar Slim, más adelante veremos algo más. Ahora vamos con la conexión a la base de datos, en la que usaremos NotORM y PDO:

<?php
require "NotORM.php";

$pdo = new PDO($dsn, $username, $password);
$db = new NotORM($pdo);

Ok, conexión creada. Vamos a suponer que tenemos una base de datos con nombres de discos. La idea sería crear un webservice que nos devolviera todos los discos de la base de datos, codificados como un objeto JSON:

<?php

$app = new Slim(
    "MODE" => "developement",
    "TEMPLATES.PATH' => "./templates"
);

$app->get("/discs", function () use ($app, $db) {
    $discs = array();
    foreach ($db->discs() as $disc) {
        $discs[]  = array(
            "id" => $disc["id"],
            "title" => $disc["title"],
            "band" => $disc["band"],
            "genre" => $disc["genre"]
        );
    }
    $app->response()->header("Content-Type", "application/json");
    echo json_encode($discs);
});

Bueno, primero creamos una instancia de Slim, definiendo que la utilizaremos en un entorno de desarrollo y apuntando en qué carpeta están las plantillas de la maquetación. Verás que en el ejemplo hemos llamado al método get(), es uno de los métodos de Slim que te enruta a una petición GET en la url que se le envía como primer argumento. Como segundo argumento le enviamos una función callback que se ejecutará como respuesta. La palabra use nos permite acceder a las variables externas desde dentro del ámbito de aplicación de la función anónima.

Ahora un ejemplo donde se haría lo mismo pero pidiendo los datos de un disco concreto:

<?php
$app->get("/disc/:id", function ($id) use ($app, $db) {
    $app->response()->header("Content-Type", "application/json");
    $disc = $db->discs()->where("id", $id);
    if ($data = $disc->fetch()) {
        echo json_encode(array(
            "id" => $data["id"],
            "title" => $data["title"],
            "band" => $data["band"],
            "genre" => $data["genre"]
            ));
    }
    else{
        echo json_encode(array(
            "status" => false,
            "message" => "No existe un disco con el id $id "
            ));
    }
});

A diferencia del anterior ves que en la ruta ahora enviamos la id del disco a buscar como parámetro.

Ok, esto nos permite insertar datos, pero ¿para insertar y modificar? Bueno, vamos a hacer un método para insertar los datos (mediante el método post() de Slim) y otro para actualizarlos (el método put()):

<?php

$app->post("/disc", function () use($app, $db) {
    $app->response()->header("Content-Type", "application/json");
    $disc = $app->request()->post();
    $result = $db->discs->insert($disc);
    echo json_encode(array("id" => $result["id"]));
});

$app->put("/disc/:id", function ($id) use ($app, $db) {
    $app->response()->header("Content-Type", "application/json");
    $book = $db->discs()->where("id", $id);
    if ($disc->fetch()) {
        $put = $app->request()->put();
        $result = $disc->update($put);
        echo json_encode(array(
            "status" => (bool)$result,
            "message" => "El disco $id ha sido actualizado"
            ));
    }
    else{
        echo json_encode(array(
            "status" => false,
            "message" => "El disco $id no existe"
        ));
    }
});

El primer método nos devuelve el id del último disco insertado, el segundo nos devuelve un valor verdadero o falso y un mensaje de error u éxito. Supongamos que quisieras acceder a esto por medio de un formulario (aunque lo normal en una de estas API es hacerlo mediante el envío de datos por la URL). ¿Cómo diferenciarías si es una nueva inserción o una edición? Fácil, crea un campo oculto llamado _METHOD y dale el valor PUT, tal cual como en el ejemplo:

</pre>
<form class="hiddenSpellError">action="#" method="post"></form>
<pre>
   <input class="hiddenSpellError" type="text" />type="hidden" name="_METHOD" value="PUT"></pre>
Title: <input class="hiddenSpellError" type="text" />type="text" name="title">
<pre></pre>
Band: <input class="hiddenSpellError" type="text" />type="text" name="band">
<pre></pre>
Genre: <input class="hiddenSpellError" type="text" />type="text" name="genre">
<pre>

   <input class="hiddenSpellError" type="text" />type="submit" value="Submit">
</form>

Ok. Nos queda el borrar datos para tener todas las operaciones CRUD en nuestra RESTful API. Ahora nos serviremos del método delete() de Slim.

<?php

$app->delete("/disc/:id", function ($id) use($app, $db) {
    $app->response()->header("Content-Type", "application/json");
    $disc = $db->discs()->where("id", $id);
    if ($disc->fetch()) {
        $result = $disc->delete();
        echo json_encode(array(
            "status" => true,
            "message" => "Disco borrado exitosamente"
        ));
    }
    else{
        echo json_encode(array(
            "status" => false,
            "message" => "El disco con id $id no existe"
        ));
    }
});

El framework Slim provee de muchas posiblidades a la hora de crear servicios web. Esto es una explicación básica de cómo se crearía cada método, pero las posibilidades son muy grandes. En su página de documentación puedes estudiar cómo sacar el 100% a este framework.

Crear un webservice básico con PHP y SOAP

SOAP es un protocolo de intercambio para servicios web basado en XML, sobre el que puedes leer en esta entrada de la wikipedia. Para no liarnos con preámbulos, vamos con la chicha ¿cómo creamos un servicio web en PHP?.

Para facilitarnos la vida empezaremos por descargar NuSOAP, un toolkit para el desarrollo de servicios web con SOAP en PHP, que nos proveerá de diversas clases para trabajar con este protocolo. Basta con descargarlo, descomprimirlo, meterlo dentro de nuestro proyecto y, cuando queramos usarlo, incluir nusoap.php como librería.

Ok, con NuSOAP instalado toca crear un servidor SOAP en nuestra aplicación. Para el ejemplo crearemos un servidor, lo llamaremos producto.php, que si recibe una petición donde se le pida una lista de libros devuelva tres títulos (es un ejemplo básico, piensa que en la realiad podrías acceder a una base de datos y dar muchas más funcionalidades).

<?php
	require_once "nusoap.php";
	 
        function getProd($categoria) {
	    if ($categoria == "libros") {
	        return join(",", array(
	            "El señor de los anillos",
	            "Los límites de la Fundación",
	            "The Rails Way"));
	    }
	    else {
	            return "No hay productos de esta categoria";
	    }
	}
	 
	$server = new soap_server();
	$server->register("getProd");
	$server->service($HTTP_RAW_POST_DATA);
?>

Ok, ahora necesitas un cliente, que llamaremos cliente.php. En el constructor, el cliente recibirá el url del servidor y para acceder al método que nos devuelve los libros recurriremos al método call(), al cual le pasaremos el nombre del método del servidor al que queremos acceder y los parámetros en forma de array. Además, también controlaremos que no haya errores en la comunicación.

<?php
	require_once "nusoap.php";
	$cliente = new nusoap_client("http://localhost/producto.php");
	 
	$error = $cliente->getError();
	if ($error) {
	    echo "<h2>Constructor error</h2><pre>" . $error . "</pre>";
	}
	 
	$result = $cliente->call("getProd", array("categoria" => "libros"));
	 
	if ($cliente->fault) {
	    echo "<h2>Fault</h2><pre>";
	    print_r($result);
	    echo "</pre>";
	}
	else {
	    $error = $cliente->getError();
	    if ($error) {
	        echo "<h2>Error</h2><pre>" . $error . "</pre>";
	    }
	    else {
	        echo "<h2>Libros</h2><pre>";
	        echo $result;
	        echo "</pre>";
	    }
	}
?>

Con esto ya tienes una idea múy básica del funcionamiento de un webservice SOAP construído con PHP. Pero claro, nos falta un archivo WSDL para tener un webservice decente. Aunque dicho archivo puede ser escrito a mano, NuSOAP puede generarlo por ti pasándole ciertos parámetros, por lo que lo ideal sería generarlo en el servidor. Así que modifica tu producto.php para que quede tal que así:

<?php
	require_once "nusoap.php";
	 
	function getProd($categoria) {
	    if ($categoria == "libros") {
	        return join(",", array(
	            "El señor de los anillos",
	            "Los límites de la Fundación",
	            "The Rails Way"));
	    }
	    else {
	        return "No hay productos de esta categoria";
	    }
	}
	 
	$server = new soap_server();
	$server->configureWSDL("producto", "urn:producto");
	 
	$server->register("getProd",
	    array("categoria" => "xsd:string"),
	    array("return" => "xsd:string"),
	    "urn:producto",
	    "urn:producto#getProd",
	    "rpc",
	    "encoded",
	    "Nos da una lista de productos de cada categoría");
	 
	$server->service($HTTP_RAW_POST_DATA);
?>

Como ves, el cambio en es cuando llamamos a register, ya que en vez de pasarle, como antes, el método en cuestión, le añadimos también varios argumentos para generar el WSDL:

  • El primer array nos permite definir el argumento de entrada y su tipo de datos
  • El segundo define la función de retorno y su tipo de datos
  • urn:producto es la definición del namespace
  • urn:producto#getProd es donde definimos la acción SOAP
  • Luego viene el tipo de llamada,que puede ser rpc, como en el ejemplo, o document
  • Tras esto definimos el valor del atribute use, que puede ser encoded o literal
  • Finalmente viene una descripción de qué hace el método al que llamamos

Ahora basta con que en el navegador accedas a producto.php?wsdl y verás el WSDL generado. Ya puedes copiarlo y añadirlo a tu directorio web (crea un archivo y llámalo, por ejemplo, libros.wsdl). Para que el cliente lo utilice debes modificar el código, y en el constructor, en vez del url le pasas el nombre del archivo, de forma que quede como en el ejemplo:

         $client = new nusoap_client("libros.wsdl", true);

Ahora sí, ya tienes montado un pequeño servicio web. El ejemplo es simplón, pero piensa en todas las funcionalidades que podrías incorporarle.

Métodos mágicos en PHP

Reconozco que no había oído hablar de esta característica de PHP 5 hasta estas navidades, cuando un experimentado programador php me comentó que era algo que debía aprender (el mismo que me recomendó aprender Symphony, por cierto). La verdad es que el nombre suena rimbobante: «Métodos mágicos»… te quedas como «no se si será una decepción o si será la leche». Luego, curiosamente durante el transcurso de una entrevista laboral me volvieron a preguntar si sabía del tema, así que decidí informarme.

Tras leer sobre el tema he de decir que no me queda muy claro del todo el uso de dichos métodos. Se trata de una serie de métodos comunes a todas las clases que se crearon para PHP5 y que refuerzan la orientación a objetos del lenguaje. Estos métodos comienzan su nombre con __ por lo que se recomienda no crear métodos propios que empiecen así. Los citados métodos mágicos son:

  • __construct()
  • __destruct()
  • __call()
  • __callStatic()
  • __get()
  • __set()
  • __isset()
  • __unset()
  • __sleep()
  • __wakeup()
  • __toString()
  • __invoke()
  • __setState()
  • __clone()

Si has programado en Java unos cuántos ya te sonarán, porque no es sólo que se llamen igual, es que tienen una funcionalidad similar.

Por lo que he entendido leyendo la documentación, el método __sleep() es llamado cuando se utiliza el método serialize(), se ejecuta antes de comenzar la serialiación y nos permite definir un array con los nombres de todas las variables del objeto que se va a serializar. Por su parte __wakeup() nos permitiría reinicilizar el objeto después de la serialización (restablecer conexiones a la base de datos, por ejemplo), y se ejecuta cuando se utliza unserialize().

Por su parte __invoke() es llamado cuando se intenta llamar a un objeto como si fuera una función. Sí, suena raro, así que os pongo un ejemplo:

<?php
class CallableClass
{
    public function __invoke($x)
    {
        var_dump($x);
    }
}
$obj = new CallableClass;
$obj(5);
?>

//esto devolvería int(5)

En cuanto a __toString(), nos permite decidir qué se imprimirá si el objeto es llamado como si fuera una cadena de texto. Por ejemplo, si haces echo $objeto.


<?php
class TesteandoToString
{
    public $imprimir;

    public function __construct($imprimir)
    {
        $this->imprimir = $imprimir;
    }

    public function __toString()
    {
        return $this->imprimir;
    }
}

$class = new TesteandoToString('Hola caracola');
echo $class;

//esto imprimiría Hola caracola
?>

El método __set_state() nos permite recoger un array con las variables exportadas por el método var_export() y asignarlas a un nuevo objeto. No confundir con la funcionalidad del método __clone(), que directamente crea una copia exacta de otro objeto.

Los métodos __call(), __callStatic(), __set(), __get(), __isset() y __unset() se utilizan para la sobrecarga, lo que nos permite «crear» dinámicamente propiedades y métodos. A estos métodos no se les pueden pasar parámetros por referencia. Se invoca a estos métodos cuando queremos trabajar con propiedades o métodos que no se han declarado o que no son visibles. El funcionamiento de __get() y __set() es similar al que pueden tener en Java los métodos get() y set(): el primero nos permite acceder a las propiedades privadas del objeto desde fuera de la clase y el segundo nos permite modificarlos. Puedes imaginar que __unset() lo que hará será «limpiar» de valor la propiedad y que __isset() funciona como isset() pero permitiendo el acceso a los valores privados. En cuanto a __call(), nos permitirá llamar a métodos inaccesibles en un contexto de objeto, y __callStatic() lo mismo pero en un contexto estático.

Finalmente __construct() es un método constructor, y será lo primero que se ejecute al crear un nuevo objeto de la clase, y __destruct() será lo último que se ejecute antes de eliminar el objeto de la memoria.

En fin, con todos estos métodos está claro que PHP gana mucho en cuanto a orientación a objetos.

Evitar SQL-injection en PHP

Los ataques SQL-Injection son unos de los más habituales en el mundo web. Aquí vamos a ver una serie de consejos para evitar estos agujeros en la seguridad:

Lo primero es seguir una serie de consejos a nivel de administración, como limitar los permisos del usuario a nivel de base de datos. Por ejemplo, en la mayoría de aplicaciones web lo habitual es que no tenga que utilizarse DROP, por lo que por seguridad sería mejor no permitir ya al usuario hacerlo. También sería interesante no dar información extra al atacante evitando sacar en pantalla los errores de la base de datos. En ese caso lo ideal es capturar el error haciendo uso de exception. Tampoco hay que confiarlo todo a las validaciones por javascript, porque el atacante puede saltárselas desactivándolo desde el navegador, por lo que mejor hacer las validaciones del lado del servidor. Y finalmente escapar las comillas con msqli_real_scape_string (en caso de que usemos MySQL), pg_scape_string (en caso de PostgreSQL) o addslashes (por si utilizamos otro SGBD). También podemos utilizar htmlentities para convertir los textos en entidades html, como un plus a la seguridad. Abajo un simple ejemplo:


<?php

try{
  $query = sprintf("SELECT * FROM users WHERE id=%d", mysqli_real_escape_string($id));
  $query = htmlentities($query);
  mysqli_query($query);
}catch(Exception $e){
    echo('Lo sentimos, ha habido un error en la conexión');
}
?>

Como medida extra se podrían utilizar expresiones regulares para evitar la inserción de ciertas palabras (SELECT, DROP, UNION…), si bien puede resultar poco práctico, sobre todo si tu software está destinado al mercado británico.

Pero si todo esto te parece lioso, hay una alternativa: la clase PDO. Dicha clase nos facilitará mucho la vida a la hora de trabajar con bases de datos, ya que nos permite abstraernos del SGDB que estemos utilizando. Si por ejemplo, en una página donde no utilices PDO o algo similar sino el mysql_connect simple, decides migrar tu web de MySQL a PostgreSQL tendrías que cambiar todos los métodos del conector de MySQL por los métodos de PostgreSQL. Con PDO bastaría con que cambiaras una sola línea de código, concretamente la de la creación del objeto PDO, y el resto de la aplicación seguiría funcionando. PDO además te permitirá usar consultas parametrizadas (como los Prepared Statements de java) o realizar transacciones. En fin, en el enlace de arriba tenéis todo el manual de PDO para estudiarlo si queréis. Ahora vamos con un simple ejemplo de Prepared Statement, para que veáis lo sencillo que es (dando por sentado para el ejemplo que ya hemos creado el objeto PDO, tal cual está explicado en el manual del enlace).


<?php
  $prepared_statement = $pdo->prepare("SELECT name FROM usuarios WHERE id = :id");/*preparamos la consulta*/
  $prepared_statement->bindParam(':id', $_GET['id'], PDO::PARAM_INT); /*Le pasamos el parámetro, asociado al parámetro de la consulta y definiendo su tipo (si no, por defecto lo trata como string)*/
  $prepared_statement->execute(); /*ejecutamos*/
  $prepared_statement = $statement->fetch(); /*recogemos los resultados, como un array. Se pueden utilizar parámetros para especificar otro tipo de respuesta, como por ejemplo PDO::FETCH_ASSOC para obtener un array asociativo*/
?>

Y con estos breves consejos lograrás que tu página sea más segura. El consejo: utiliza PDO, por ahorrarte comeduras de cabeza, por seguridad y por portabilidad de tu código.

Evitar ataques XSS con PHP Input Filter

Hoy una lección de seguridad en programación web: Evitar que a vuestra página le hagan un ataque por XSS (Cross Site Scripting). Si no sabéis lo que es el Cross Site Scripting… os lo explica mejor la wikipedia y así me centro en el tema (una vez le hice un ataque de estos a la página de un grupúsculo neonazi que redirigía a un vídeo del desfile del orgullo gay en Youtube)

Bueno, hay frameworks como Symphony o CakePHP que ya se encargar de implementar este tipo de seguridad, al igual que también lo hacen ciertos gestores de contenidos. Pero si se da el caso de que no estás usando ninguno, estás haciendo PHP «a pelo», lo mejor será que recurramos a la clase PHP Input Filter. Dicha clase permite filtrar código malicioso ingresado en los formularios para prevenir ataques XSS de manera sencilla, pero tiene la cualidad de no limpiar determinadas etiquetas o atributos si queremos.

Para utilizar esta clase, la descargaremos desde el enlace anterior e incluiremos class.inputfilter.php al inicio de nuestro códgi. Luego crearemos una instancia de la clase InputFilter, entonces podremos filtrar los datos con el método process:

    require_once("class.inputfilter.php");
    $filter = new InputFilter();
    $variable = $filter->process($_POST['variable']);

Esto nos permitiría limpiar de etiquetas la variable enviada por $_POST llamada variable. ¿Y si queremos limpiar todos los campos enviados por el método post? Pues basta con pasarle todo el array:

$_POST = $filter->process($_POST);

Y con eso tendríamos el array $_POST limpio de etiquetas y securizado.

Pero ¿y si queremos permitir ciertas etiquetas? Imaginemos que desde un input text metemos texto formateado, y nos interesa que sí puedan subir saltos de línea, texto en negrita o cursiva. Pues muy sencillo también, ya que basta con pasar en la creación del objeto InputFilter un array con las etiquetas que queremos conservar como parámetro:

    $filter = new InputFilter(array('em', 'i', 'br', 'b', 'strong'));
    $_POST = $filter->process($_POST);

Y esto se puede llevar más allá, porque también podemos decir que se permitan ciertos atributos de ciertas etiquetas. Por ejemplo, imaginemos que queremos permitir que inserten enlaces junto a su href y a su id, pero ningún atributo más:

    $filter = new InputFilter(array('a'), array('href', 'id'));
    $enlace = $filter->process($_POST['enlace']);

Tras el array de etiquetas pasamos otro array de atributos, simplemente.

Con estos sencillos consejos lograrás que tus formularios sean más seguros en PHP.

Botón de «Compartir en Facebook», «Compartir en Twitter» y «+1» de Google+

¿Deseas integrar un botón de «compartir en Facebook en tu página»? Es una opción muy útil para que tus lectores hagan publicidad de tu sitio en la popular red social. Y como por otra parte eso también es publicidad gratuita para ellos ya se han encargado de que la cosa sea facilita.

Antaño la cosa se hacía con un simple javascript, pero a día de hoy Facebook incluso te facilita la creación del botón con un formulario en su página de desarrolladores

Con Twitter, tres cuartos de lo mismo: un simple formulario y te genera botones para compartir, mencionar, like, etc en la popular red de microbloggin.

En cuanto a Google+, la cosa tampoco es compleja. En su API de Javascript no sólo te dan un formulario de creación sino que también te facilitan una explicación de todo el funcionamiento del botón.

En definitiva, cualquiera de las tres redes sociales más populares te facilita la vida a la hora de crear un botón de compartir que integrar en el código de tu página o blog.

Instalar PHPUnit en WAMP

Inciso antes de empezar: Estoy buscando información y cursos de Symphony 2, porque me han recomendado aprender sobre este framework (ya que el destino parece empujarme a trabajar en PHP, si la vida te da limones haz mucha limonada para meter en tu currículum), si alguien puede aportar algo sobre el tema, por favor, en comentarios.

Y seguimos con el tema, instalar PHPUnit en un servidor Apache en Windows (WAMP).

Bueno, habría que empezar por decir ¿por qué usar PHPUnit? Pues para poder realizar tests automatizados sobre nuestro código PHP de manera eficiente. ¿Cómo lo instalamos en nuestro servidor? Bueno, todo es ir en cómodos pasos:

NOTA: En el artículo original lo hacíamos con PEAR, pero se le quitó el soporte hace años. Editamos para ver cómo hacerlo con PHAR:

  • Añade el directorio (en mi caso «c:\wamp\bin\php\php5.3.4») php a tu PATH
  • Descargamos el fichero PHAR desde https://phar.phpunit.de/phpunit-7.phar (Ojo, puede cambiar la versión con el paso del tiempo) y lo guardamos como C:\bin\phpunit.phar
  • Después ejecutamos el siguiente comando:
C:\Users\username> cd C:\bin
C:\bin> echo @php "%~dp0phpunit.phar" %* > phpunit.cmd
C:\bin> exit
  • Abre un nuevo prompt en línea de comados y comprueba que se ha instalado correctamente con el siguiente comando:
C:\Users\username> phpunit --version

Ok, ahora debería estar funcionando e instalado. Lo mejor es hacer un test de prueba para ver si funciona todo. En este caso una tontería básica de la que sabemos el resultado: comprobaremos que uno es igual a uno.

  class MyTest extends PHPUnit_Framework_TestCase
  {
    public function testUnoIgualUno()
    {
      $this->assertEquals(1, 1);
    }
  }

Ahora desde otro terminal basta ejecutar phpunit MyTest.php y este debería devolverte como respuesta el número de versión de PHPUnit, el tiempo que necesitó para la operación, la memoria consumida y un mensaje como este: OK (1 test, 1 assertion)

Todavía no he profundizado mucho con este software, pero cuando tenga tiempo en el trabajo espero poder ponerme con ello porque facilita mucho la vida el poder realizar tests de forma organizada.

Editores WYSIWYG para tu web

¿Necesitas un editor WYSIWYG para integrar en tu página web? ¿Quieres mandar e-mails con texto enriquecido? ¿Quieres que tus usuarios puedan generar código con texto formateado? Ok, pues estas son algunas de las mejores opciones libres a las que puedes recurrir:

  • TinyMCE: Usado por WordPress, Facebook, Oracle Beehive, IBM Web CMS, Joomla, Episerver… en fin, son nombres que deberían dar confianza al usuario. TinyMCE incluye una enorme variedad de opciones que tú puedes configurar y decidir cuales usar. Es fácil de integrar y tiene una amplia documentación.
  • NicEdit: Dos motivos para plantearse el uso de NicEdit son su ligereza y su fácil integración (sólo requiere dos líneas de código y lo tendrás funcionando). No tiene tantas opciones como el anterior pero son suficientes para el uso habitual del usuario, lo que además hará que para este sea más fácil e intuitivo usarlo.
  • openWYSIWYG: Reconozco que no lo he probado, pero me han hablado de él. Por lo que me han comentado el proyecto está un poco abandonado, así que es posible tener problemas de compatibilidad con las últimas versiones de algunos navegadores.
  • CKEditor: A nivel de funcionalidades implementadas está en la misma liga que TinyMCE, y es el editor utilizado por Drupal. Muy potente y con gran cantidad de opciones. Cuando lo veas parecerá que estás ante el procesador de texto de una suite ofimática.
    CKEditor
    CKEditor

     

En fin, con estos cuatro más o menos ya vemos todo lo que hay en el mercado. ¿Y cómo los implementas? Pues mira la documentación de cada uno. ¿Y cómo recoges los datos? Tranquilo, al procesar el formulario te vendrá como el resultado de un textarea normal, al menos en PHP (las versiones para Java o ASP ya vendrán en su documentación explicadas, digo yo).