Egresado de Psicología PUCV
Front y programación en AyerViernes y clerk.im
Blogueo sobre Internet, tecnología, FOSS, etc. en yukei.net y sobre otras tonteras en contrasentido.net
Me puedes contactar en felipe.lavin@gmail.com
Si bien existen mil formas de detectar dispositivos móviles, a veces necesitamos algo más sencillo y rápido de implementar, que nos permita diferenciar fácilmente entre las plataformas móviles más populares..
php-mobile-detect es una clase en PHP para detectar las plataformas móviles más importantes: Android, iOS, BlackBerry, Opera Mini, Palm, Windows Mobile y móviles genéricos. Además, permite diferenciar entre móviles y tablets.
Su forma de funcionamiento es muy sencilla:
<?php
include('Mobile_Detect.php');
$detect = new Mobile_Detect();
if ( $detect->isAndroidtablet() || $detect->isIpad() || $detect->isBlackberrytablet() ) {
// mostar versión para tablets
} elseif( $detect->isAndroid() ) {
// versión Android
} elseif ( $detect->isIphone() ) {
// versión iPhone
} elseif ( $detect->isMobile() ) {
// versión para otros móviles
} else{
// versión "normal"
}
?>
La lista completa de métodos es: isAndroid(), isAndroidtablet(), isIphone(), isIpad(), isBlackberry(), isBlackberrytablet(), isPalm(), isWindowsphone(), isWindows(), isGeneric(), isMobile()
Como saben los regulares de este blog, hace bastante tiempo me he rendido ante Bazaar, el sistema de control de versiones distribuido creado por Canonical y parte del proyecto GNU; más poderoso que SVN, más simple que git… en fin.
Una secuencia de acciones me llevó a una situación terrible: por un momento pensé que había perdido un conjunto de cambios del historial. La condiciones fueron más o menos las siguientes:
bzr bind, con lo se aplicaron una serie de cambios que estaban en el repositorio remotoEn resumen, lo que había ocurrido era que había cambiado de línea temporal (al mejor estilo Fringe). Transformar nuevamente la copia en una rama no solucionaba nada, sin embargo suponía que esa revisión debía existir en el repositorio…. ¿cómo restituirla?
La respuesta es conceptualmente sencilla: todo lo que necesitamos hacer es traer los cambios de esa revisión al estado actual de nuestro árbol de trabajo; y a pesar que los números de revisión de bzr son dígitos, en realidad cada commit tiene un identificador único que podemos utilizar para recuperar esos cambios.
En este caso, para recuperar esos cambios debemos ejecutar en primer lugar bzr heads --all, con lo que podremos ver las últimas versiones que conviven en el historial de cambios, por ejemplo:
TIP of branch: /var/www/repo.bzr/master/
HEAD: revision-id: user@domain.com-20111220131621-ao5rkri1o80evnhh
committer: Felipe Lavín <user@domain.com>
branch nick: master
timestamp: Tue 2011-12-20 10:16:21 -0300
message:
mensaje del commit
Luego, para recuperar los cambios extraviados:
bzr pull . --overwrite -r revid:user@domain.com-20111220131621-ao5rkri1o80evnhh
… y podemos seguir trabajando con normalidad.
Tras el cierre de MegaUpload y otros servicios para compartir archivos, muchos han optado por volver a visitar a un viejo conocido: BitTorrent (el protocolo, no el cliente).
Afortunadamente, los clientes más nuevos y populares han incluido un par de opciones que nos permiten aumentar (aunque sea sólo un poco) el nivel de privacidad de nuestras conexiones.
Las opciones que nos interesan son fundamentalmente dos:
Adicionalmente, si te sientes especialmente paranoico, puedes desactivar el intercambio de pares a través de DHT, puesto que al activar esta opción vas a compartir tu dirección IP y otros datos a través de una red distribuída — por otra parte, al desactivarla probablemente vas a tener menos pares y vas a depender en mayor medida de los pares que estén registrados en el tracker central.
Transmission es cliente pequeño y sencillo, pero con las opciones justas. Está para varias distribuciones de Linux (en Ubuntu viene preinstalado) y Mac.
Para activar estas opciones, debemos ir a Editar → Preferencias y luego a la pestaña Privacidad.
Si deseas desactivar el intercambio de pares por DHT, puedes hacerlo en la misma pestaña.
Deluge es un cliente liviano y multiplataforma, disponible para Linux, Mac y Windows.
Para activar las opciones de privacidad, debes ir a Editar → Preferencias y luego
Finalmente, si quieres desactivar DHT, debes hacerlo también desde la categoría de Red, en la sección de Extras de red.
A principios de año, Herbert me invitó a participar de algunas clases en su curso de Taller de construcción para alumnos de 4º año de la e[ad]. Lo que en un principio estaría dedicado a algunas lecciones de Javascript como contexto general del diseño de interacción en la Web, pronto mutó a acercarnos mucho más al proyecto que este curso se había planteado como meta.
La plataforma Estorninos es un espacio diseñado para la conformación de una comunidad, donde los alumnos se puedan formar en un cuerpo organizado, desde el cual participen en el hacer universidad
, que se concreta a través de 4 módulos de abierta participación: proyectos, debates, eventos y notas.
El desarrollo del proyecto está en un estado alpha funcional, y continuará su marcha durante el próximo año, con el objetivo de convertirse en una solución extensible bajo la forma de un conjunto de un tema y plugins para WordPress, distribuido libremente bajo una licencia FOSS. El proyecto está ampliamente documentado en la Wiki de e[ad], donde pueden ver sus fundamentos, metas y logros.
Hace ya algunos meses estoy utilizando Bazaar como sistema de control de versiones para todos mis proyectos nuevos, con resultados muy satisfactorios: me resulta muchísimo más potente que Subversion (SVN) por su funcionamiento como sistema distribuído, y a la vez más sencillo de usar que git (del que sólo le podría faltar la velocidad).
Uno de estos proyectos ha sido el rediseño de un sitio bastante grande y complejo que hemos desarrollado en AyerViernes y que hasta ahora se encuentra versionado con svn, pero que queremos trasladar a Bazaar por la buena experiencia que hemos tenido. En este proyecto frecuentemente se realizan cambios al modo de funcionamiento de sus diversas características o se agregan nuevas funcionalidades, por lo que no podíamos trabajar bajo el supuesto de congelar el trabajo en el sitio actual y migrar todo inmediatamente a la nueva versión en desarrollo; en síntesis, debíamos ser capaces de:
Afortunadamente, Bazaar puede interoperar con Subversion gracias a un plugin llamado (adecuadamente) bzr-svn, disponible en los repositorios de Ubuntu.
La estrategia que utilizamos demuestra la flexibilidad y potencia de Bazaar. Los pasos a seguir serían aproximadamente los siguientes:
Si aún no lo tienes, lo primero es instalar el plugin bzr-svn. En Ubuntu esto se puede lograr con sudo apt-get install bzr-svn desde el terminal.
Luego, crear un repositorio compartido bajo el cual almacenaremos tanto la versión online (en producción) como sobre la cual trabajaremos el rediseño (versión de desarrollo), cada una de ellas como una rama (branch).
Al utilizar un repositorio compartido, las revisiones se almacenan en el repositorio en lugar de en cada rama, lo que permite optimizar drásticamente la utilización de espacio y crear nuevas ramas velozmente. Para inicializar el repositorio compartido, debemos ejecutar bzr init-repo proyecto.repo
Una vez que está creado el repositorio compartido, nuestro objetivo será importar los archivos y el historial del proyecto desde el repositorio SVN donde se está trabajando actualmente, lo que podemos realizar de diversos modos dependiendo de la forma en que esté organizado el repositorio SVN.
Para ello contamos con dos opciones proporcionadas por el plugin: podemos importar solo una parte del repositorio SVN (por ejemplo, solamente el trunk o una de las ramas) o bien hacer una copia completa del repositorio (incluyendo todas las ramas y etiquetas además del trunk).
Para el primer caso, tenemos la opción de crear una nueva rama a partir de la versión seleccionada tal como si lo estuviésemos haciendo desde una rama de Bazaar: bzr branch svn://servidor.com/proyecto trunk, con lo que Bazaar importará todo el historial de versiones a la nueva rama junto con crear un árbol de trabajo con la última versión de los archivos. Por otra parte, si deseamos que los commits en este árbol siempre se suban al repositorio svn, también contamos con la opción de hacer un checkout (o bien pasar desde una rama a un checkout con bind/unbind).
Para el segundo caso, podemos utilizar el comando bzr svn-import svn://servidor.com/proyecto repositorio. Bazaar importará todo el historial de versiones, pero no creará el árbol de trabajo a menos que agreguemos la opción --trees.
Suponiendo que hemos utilizado la primera de las opciones recién indicadas, tendríamos lo siguiente:
$ cd /var/www # Inicializar el repositorio compartido $ bzr init-repo proyecto.repo # Importar el historial del proyecto $ cd proyecto.repo $ bzr branch svn://servidor.com/proyecto trunk
Y llegamos finalmente al momento en que comenzaremos a trabajar en la nueva versión. Para ello, crearemos una nueva rama en el repositorio compartido, donde ejecutaremos todos los cambios necesarios para el desarrollo de la nueva versión.
# Crear rama de desarrollo $ cd /var/www/proyecto.repo $ bzr branch trunk feature-branch $ cd feature-branch # hack, hack, hack...
A partir de este punto, lo que queda es introducir todas las modificaciones que sean necesarias en nuestra nueva versión — dado que es una rama, los commits de cambios serán locales al repositorio. Nuestro flujo de trabajo sería básicamente el siguiente:
De este modo, la mantención del proyecto puede continuar de forma paralela al nuevo desarrollo, sin cruzarse entre sí a menos que así lo queramos. Si hubiesen cambios en el sitio en producción que se envíen al repositorio SVN, podríamos integrarlos dentro de nuestra versión de desarrollo con los siguientes pasos:
# Ingresamos a la rama ligada al sitio en producción $ cd /var/www/proyecto.repo/trunk # Obtener los cambios desde el repositorio SVN $ bzr pull # O bzr up si es un checkout # Cambiar a la rama en desarrollo $ cd ../feature-branch # Incorporar los cambios de producción al nuevo desarrollo $ bzr merge ../trunk
Del mismo modo, cuando queramos integrar los cambios de la versión en desarrollo a la rama principal, también recurriremos a bzr merge, de modo de preservar el historial que la rama en producción (el “trunk” del ejemplo).
$ cd /var/www/proyecto.repo/trunk # Mezclar cambios de desarrollo en la versión de producción $ bzr merge ../feature-branch
Es importante recalcar la utilización de merge, y no un push desde feature-branch al trunk, ya que de otro modo sobreescribiremos el historial de versiones del trunk.
Ya en este punto, podremos chequear que todos los cambios que introdujimos se complementan bien con los últimos cambios del sitio en producción. Una vez que se hayan alisado todas las asperezas, podemos enviar finalmente nuestros cambios desde /var/www/proyecto.repo/trunk con un bzr push hacia el repositorio SVN.
Hasta acá tenemos la versión simplificada, pero lo más probable es que durante el desarrollo debamos cooperar con compañeros de equipo encargados de otras piezas del puzzle… a partir de lo anterior, podemos seguir expandiendo el modelo para incorporar estas nuevas posibilidades: nuestros compañeros pueden crear nuevas ramas locales en sus respectivos equipos, o bien montar un checkout donde implementar cambios que luego serán enviados a nuestro repositorio.
De este modo, una versión más completa del esquema anterior sería la siguiente:
Como se puede ver, existen muchas alternativas para organizar el trabajo en la forma que sea mejor para tu equipo; y lo que es mejor aún, es muy fácil implementar otras variantes que vayan siendo más apropiadas según el desarrollo del proyecto.
Supongamos el siguiente escenario: estás desarrollando un metabox para un tipo personalizado de contenido que representa a personas, y en el que debes agregar información de contacto como teléfono, correo electrónico, dirección, etc; la que se mostrará junto a cada persona como una ficha.
Una opción para guardar estos datos sería recurrir a alguna convención de nombres de modo que cada dato se almacena como una fila en la tabla $wpdb->postmeta; algo como _persona_telefono, _persona_email, _persona_direccion, etc. Luego, al mostrar los datos podríamos hacer una consulta como SELECT * FROM $wpdb->postmeta WHERE post_id = $post_id AND meta_key LIKE '_persona%'.
Sin embargo, una mejor alternativa en este tipo de casos sería recurrir a la utilización de datos serializados, ya que nos permitirán guardar en un solo campo una estructura compleja de datos como un array (uni o multidimensional) o un objeto; lo que nos puede facilitar de forma importante varias tareas si planificamos con cuidado nuestra estructura de datos.
Me atrevería a decir que en general los especialistas en bases de datos relacionales no miran con muy buenos ojos la utilización de este tipo de técnicas (ya que idealmente, cada objeto debiese estar modelado de acuerdo a un esquema que permita optimizar el rendimiento de la base de datos), sin embargo en WordPress muchas veces nos encontraremos con la necesidad de guardar un conjunto limitado (no necesariamente fijo) de datos relacionados y sin un esquema inmutable en la base de datos, ya sea como metadatos de un post (o un tipo de contenido personalizado), de un comentario o un usuario, o bien como opciones de un plugin — convenientemente, WordPress nos provee de APIs para interactuar de forma sencilla con la base de datos en estos casos, en los que la serialización de datos ya está considerada como parte del proceso de lectura/escritura desde/hacia la base de datos.
Por lo tanto, el trabajo con datos serializados nos presenta una serie de ventajas, como:
Como decía anteriormente, WordPress nos hace este trabajo muy simple, ya que las APIs de metadatos para posts, comentarios y usuarios, tanto como el API de opciones ya contemplan la posibilidad de trabajar con datos serializados.
Retomando el ejemplo del principio:
// esta es la información sanitizada a partir del envío del formulario $person_data = array( 'tel' => '+1 012 345 678', 'email' => 'homero@plantanucleardespringfield.com', 'adr' => array( 'street-address' => 'Avenida Siempre Viva 742', 'locality' => 'Springfield', 'region' => '??' ) ); // para guardar los datos // (el "_" antes del nombre de la opción hace que // no se vea en la lista de campos personalizados) update_post_meta($post->ID, '_person_data', $person_data); // para obtener los datos // devuelve un array similar a $person_data get_post_meta($post->ID, '_person_data', true);
No es necesario serializar los datos antes de guardarlos ni des-serializarlos al obtenerlos, ya que WordPress internamente determinará si es necesario hacerlo (mediante las funciones maybe_serialize y maybe_unserialize, respectivamente).
Quizás alguien a estas alturas estará pensando “¿bueno, y cuáles son las desventajas?”… muy suspicaz, ¿eh? Quizás no lo suficiente.
Al serializar el array anterior, la información que se guarda en la base de datos corresponde a:
a:3:{s:3:"tel";s:14:"+1 012 345 678";s:5:"email";s:36:"homero@plantanucleardepsringield.com";s:3:"adr";a:3:{s:14:"street-address";s:24:"Avenida Siempre Viva 742";s:8:"locality";s:11:"Springfield";s:6:"region";s:2:"??";}}
En primer lugar, habría que plantear lo obvio: cada vez que obtienes el valor necesitarás transformarlo a su representación correcta (array u objeto). A partir de ello, no tiene mucho sentido usar esta técnica cuando los datos que se almacenan no tienen mucha relación entre sí y se utilizan siempre de forma individual. Por otra parte, tampoco convendría guardar cantidades demasiado grandes de información de este modo, ya que el gasto de procesamiento y memoria sería demasiado alto.
El valor serializado que se guarda en la base de datos es simplemente una cadena de texto … el problema surge cuando queremos buscar algún dato en particular (ya que no será tan sencillo como buscar en un campo que tiene un texto simple) o bien al utilizar un dato como condición en en SELECT (por ejemplo, cuando se utiliza un campo de la tabla postmeta para obtener un conjunto de posts).
Sin embargo… aquí si conviene ser más estricto en temas de bases de datos, ya que en todos los casos contemplados (meta datos de posts, usuarios, comentarios; opciones) el campo donde se almacenan los valores (meta_value, option_value, etc) no tiene índice, por lo que las consultas que utilizan estas condiciones están fatalmente sub-optimizadas: por ejemplo, al hace una consulta como SELECT * FROM $wpdb->postmeta WHERE meta_key = '_persona_ciudad' AND meta_value = 'Springfield', la base de datos debe revisar todos los registros de la tabla en busca de coincidencias (esto no ocurre al hacer consultas como SELECT * FROM $wpdb->postmeta WHERE post_id = $post_id AND meta_key = '_person_data' ya que en esas columnas existen índices que permiten que la base de datos devuelva rápidamente los valores coincidentes con los criterios indicados).
Por lo tanto, si deseas guardar muchos datos que pueden servir como criterios de búsqueda, la mejor opción en ese caso será crear una tabla especial para esa información, que te permita definir los índices adecuados según las necesidades del programa.
Siempre me ha llamado profundamente la atención esa costumbre que tienen algunos clientes de preferir proveedores de hosting nacionales… no es que tenga nada en contra de los proveedores nacionales por el hecho de ser nacionales, sino porque son comprobadamente y rematadamente pésimos — por cierto, me refiero particularmente al escenario de Chile, desconozco cómo será el panorama en otros países pero tengo la impresión que puede pasar algo similar.
Pensando un poco por las razones que uno podría tener para dispararse en el pie de este modo, creo que hay al menos tres motivos que podrían influir en esta decisión.
… después de todo, no es tan descabellado pensar que son expertos en infraestructura y deberían tener las competencias para poder manejar ambos aspectos del negocio… lo que sabemos que no es necesariamente cierto: en general el servicio de hosting que venden los ISP está atado al paquete de servicios contratados o bien es tan limitado que no aguanta nada que se más que un simple sitio tipo panfleto.
La búsqueda que sigue a partir de este punto suele terminar con alguno de los resultados de la primera página para “hosting {inserte su país aquí}” en Google: por lo general con una web que parece un homenaje a los 1990s, y que se preocupa de utilizar términos que parecen muy técnicos pero no aportan nada.
A pesar de que prácticamente todos los navegadores se han preocupado de aumentar y resaltar sus características de seguridad, al tipo de cliente que prefiere contratar un hosting nacional le preocupa más que le puedan hacer un cargo en la tarjeta de crédito (probablemente porque ha visto algún reportaje en las noticias de la televisión o en alguna película de hackers) a que lo estafen mensualmente en su cara, y contratar un servicio malo que puede pagar con un cheque o una transferencia bancaria a uno que debe pagar con tarjeta de crédito en un servicio que le puedas recomendar.
Lo criticable no es el hecho de querer tomar sus decisiones en torno al servicio que quisieran contratar, más bien que de fondo probablemente está la idea que su sitio es simplemente uno más de los gastos de la oficina, como el agua o la electricidad, y que con el solo hecho de pagar la cuenta mensualmente su sitio debiera funcionar por sí mismo, sin preocuparse de crear contenidos ni hacer ningún tipo de mantención — es el tipo de sitio que encuentras con una noticia con más de un año de antigüedad… sobre su nuevo sitio.
Probablemente el argumento más poderoso a la vez que el más engañoso. En lo personal, me parece inexplicable la especie de fascinación que a algunas personas les produce tener un “ejecutivo de cuenta” que les plantee un servicio “a la medida”, como si se tratara de una cuenta de banco o un sastre.
Por otra parte, está la confianza ciega en que el personal de servicio técnico hable en tu idioma, lo que difícilmente podría ser una ventaja ya que si hay un fallo en el sitio o si por alguna razón el sitio se ve comprometido, el servicio técnico del hosting no es el que va a responder ni solucionar el problema: si el problema es a nivel de la aplicación, con razón podrían argumentar que no es de su responsabilidad (aunque si es así, no tiene mucho sentido contar con el servicio técnico del hosting, sino más bien con una mantención de quien desarrolló el sitio, ¿no?), pero por otra parte, si el problema es realmente de más bajo nivel y responsabilidad directa del hosting, entonces la cuestión no debería recaer en que puedas llamar a alguien para que solucione el problema, sino en que esos problemas no se produzcan, y si bien todo sistema es susceptible a fallos, un buen proveedor no necesita que le digan “esto está fallando” para saber que tiene algo que solucionar.
La trampilla del “tener a quién llamar” pasa también por vender cosas que no son tal como las pintan: por una parte, están los que promueven a cPanel o Plesk como entornos “amigables” o “autoadministrables” (vaya a saber uno qué significa esto para ellos) como si cualquier persona fuera a entender mágicamente todas las opciones que se le ofrecen; mientras que por otra están los que se ufanan de tener un panel de control propio y que salvo contadas excepciones suelen ser engendros horripilantes y poco funcionales.
Finalmente, están también los que exhiben como medallas de guerra sus certificaciones de Microsoft, Oracle y Java, pero que te miran como si estuvieras hablando en zulu (o peor, condescendientemente como a un párvulo) cuando planteas que estás trabajando sobre PHP+MySQL, WordPress y “todas esas cosas hippientas de software libre/código abierto”. Algunos llegan a afirmar que nadie da soporte a “esas cosas”, por lo que ellos sólo garantizan, básicamente, que el servidor está conectado a la electricidad, pero de ahí en más no es su responsabilidad.
No estoy tratando de hacer una fábula, pero hay algunas cosas que podemos sacar en limpio:
Siempre trata de anticipar y solucionar los escollos que puedan encontrar en este paso que debería ser un mero trámite. Un desarrollo no implementado le sirve tan poco a tu cliente como a tu portafolio y reputación.
(cc) Lizzybethhh (flickr)
… a pesar que desde Twitter y Facebook, ahora todos los años alguien dice que los blogs se acabaron, aún quedamos algunos dando vueltas… aunque publiquemos cada vez menos — se me hace más posible que hayan menos blogs (como los de antes, quiero decir) porque todos los bloggers consiguieron trabajo (gracias a sus blogs) más que cualquier otra cosa… al final, sólo es falta de tiempo.
Aunque tampoco debiera ser tan fatalista: desde el año anterior hasta ahora, estoy con un promedio de 1 post por mes (que es poco, pero es mejor que nada)… y continuando con los anuncios que no le importan a nadie: estoy probando un cloud server en Rackspace (también-conocido-como “humilde servidor”, props para @pedroarellano) y acabo de dar de baja un servicio de publicidad que prometía mucho pero resultaba una molestia más que nada (no para mí, sino para los pocos valientes que aún se pierden por acá)… ¡ah! y por fin tengo un proceso de desarrollo ordenado (ya no más “en casa de herrero, cuchillo de palo”).
En fin… si me dedico a terminar el montón de borradores que tengo por ahí, queda yukei.net para rato.
Haca ya bastante tiempo mi editor de código de cabecera es Komodo Edit, que además de ser gratuito y multiplataforma, tiene varias características que lo hacen muy útil pero manteniendo la simplicidad.
Quizás uno de sus puntos débiles es que no existen paquetes disponibles para Ubuntu ni Debian, por lo que su actualización es un poco menos que obvia, pero de todos modos resulta bastante sencilla.
Al modo de Firefox, Komodo te notificará cuando exista una nueva versión disponible (al menos cuando se trate de actualizaciones menores), pero junto con eso presentará un aviso que, en resumen te indicará que con tu cuenta actual no tienes privilegios para poder actualizar el software.
Para solucionar esto, la forma más sencilla es abrir la terminal y dirigirte al directorio donde está instalado Komodo, en mi caso, /var/opt/active-state/. Una vez en esa carpeta, debes iniciar el programa como administrador, lo que puedes hacer de forma fácil y segura (con la tranquilidad que no existirán cambios de permisos u otros que pudieran dificultar el uso posterior) con gksu bin/komodo.
Una vez iniciado el software, dirígete al menú Help → Check Updates y ejecuta la actualización. Reinicia el programa (aun como gksu) y listo… ya puedes volver a ejecutarlo como usuario normal.
wp_parse_args() es una función de WordPress que nos permite contar con tres interesantes beneficios al escribir una función:
Según el Codex: se usa a través de WordPress para evitar tener que preocuparse sobre la lógica de las opciones predeterminadas y los inputs, y produce un patrón estable para pasar argumentos.
Aprovecharlo en tus funciones es muy sencillo. Veamos algunos ejemplos.
Supongamos que queremos tener una función muy sencilla para mostrar la fecha actual, pero a la que queremos dar algo de flexibilidad para, por ejemplo, poder mostrar otras fechas que le podamos indicar como parámetro.
function show_date( $args = null ){
$s = wp_parse_args( $args, array(
'format' => 'j F Y',
'date' => time(),
'echo' => false,
'class' => 'date-now',
'translate' => true
) );
$out = '<span class="'. esc_attr( $s['class'] ) .'">';
if ( $s['translate'] ) {
// si queremos obtener la fecha en el idioma de la instalación de
// WordPress, utilizaremos la función date_i18n()
$out .= date_i18n( $s['format'], $s['date'] );
} else {
$out .= date( $s['format'], $s['date'] );
}
$out .= '</span>';
if ( $s['echo'] ) echo $out;
else return $out;
}
En este caso, la mayoría de las veces podríamos utilizar la función llamando simplemente a show_date( ), sin ningún parámetro (ni siquiera $args es requerido), pero en otros casos contamos con una buena cantidad de opciones para poder reutilizar la función en distintos contextos, por ejemplo: show_date('echo=0&class=otra-clase').
En este caso, dado que podríamos utilizar la función sin indicar ningún parámetro, en la definición de la función $args es igual a null, ya que wp_parse_args() espera recibir exactamente dos parámetros: los argumentos que la función está recibiendo ($args) en forma de array o query string, y un array de valores predeterminados.
Por supuesto, también se puede dar el caso que tu función necesite recibir argumentos para hacer lo suyo; en ese caso podrías declarar esos argumentos de forma separada a los que trabajará wp_parse_args.
Por ejemplo, una función que suelo utilizar para construir select:
/**
* Create an HTML select
* @param array $els Array with the select options, the array key is the "value" attribute that will be sent with the form and the array value is the option text
* @param array|string $args Select attribute options, selected items and other arguments
* @return string Select
* @author Felipe Lavín <felipe@yukei.net>
**/
function create_select($els, $args){
$s = wp_parse_args($args, array(
'id' => null,
'echo' => false,
'size' => null,
'class' => null,
'style' => null,
'multiple' => false,
'selected' => null,
'__checkboxes' => true,
'show_option_all' => false,
'show_option_none' => false,
));
$multiple_values = ( is_array( $s['selected'] ) ) ? true : false;
$do_cb = ( $s['__checkboxes'] && ( $multiple_values || $s['multiple'] ) ) ? true : false;
$atts = ( $do_cb ) ? array('id', 'class', 'style') : array('id', 'name', 'class', 'size', 'multiple', 'style');
$selected = $do_cb ? ' checked="checked"' : ' selected="selected"';
if ( !empty($els) ) {
$out = ( $do_cb ) ? '<ul' : '<select';
foreach($atts as $k){
if ( !is_null( $s[$k] ) && $s[$k] !== false ) {
switch($k):
case 'multiple':
$out .= ' multiple="multiple"';
break;
case 'name':
$out .= $s['multiple'] ? ' name="'. $s['name'].'[]"' : ' name="'. $s['name'] .'"';
break;
default:
$out .= ' '. $k .'="'. esc_attr( $s[$k] ) .'"';
endswitch;
}
}
$out .= '>';
if (!$do_cb ) {
// "none" could be empty, but "all" should be a string
if ( $s['show_option_none'] !== false ) {
if ( is_array( $s['show_option_none'] ) ) {
$out .= '<option value="'. key( $s['show_option_none'] ) .'">'. current( $s['show_option_none'] ) .'</option>';
} else {
$out .= '<option value="-1">'. $s['show_option_none'] .'</option>';
}
}
if ( $s['show_option_all'] != false ) $out .= '<option value="_all">'. $s['show_option_all'] .'</option>';
}
foreach ( $els as $key => $val ) {
if ( !$multiple_values ) $active = $s['selected'] == $key ? $selected : null;
else $active = in_array( $key, $s'selected'] ) ? $selected : null;
// So we can directly pass query results
if ( is_object( $val ) && isset( $val .'_'. $key .'"><input'. $active .' type="checkbox" value="'. $key .'" name="'. $s['name'] .'[]" id="cb_'. $s['id'] .'_'. $key .'" /> '. $val .'</label></li>';
else
$out .= '<option value="'. $key .'"'. $active .'>'. $val .'</option>';
}
$out .= ( $do_cb ) ? '</ul>' : '</select>';
if ( $s['echo'] ) echo $out;
else return $out;
} else {
return false;
}
En este caso los dos parámetros son requeridos: el primero porque… porque necesitas elementos para poder construir el select; y el segundo porque determina el output que produce la función.
Algunas notas para finalizar:
query_posts, get_posts o crearás objetos de WP_Query es buena idea filtrar qué argumentos pasarán de un lado a otro.Ah, y por cierto, en jQuery puedes lograr algo bastante similar con jQuery.extend()
Porque el socialismo no es sólo una doctrina obrera, sino que representa el ateísmo en su forma contemporánea; es la cuestión de la torre de Babel, que se construyó a espaldas de Dios no por alcanzar el cielo desde la tierra, sino por baja a la tierra el cielo.
Los hermanos Karamazov
Tags: Literatura, política, religión, socialismoEl verdadero realista, si es incrédulo, halla siempre en sí mismo la voluntad y la energía para no creer en el milagro, y si éste se le presenta como un hecho incontrastable, dudará de sus sentidos antes que admitir el hecho. Y si lo admite, lo considerará como un hecho natural que anteriormente no conocía. Para el realista no es la fe lo que nace del milagro, sino el milagro el que nace de la fe.
Los hermanos Karamazov
Tags: ateísmo, Literatura, religiónEl movimiento estudiantil, surgido en las universidades pertenecientes al Consejo de Rectores, y al cual se han sumado académicos y autoridades, ha puesto en evidencia algo que estaba a la vista, y que sin embargo los chilenos nos negábamos a ver. El escándalo de la educación en Chile: colegios municipalizados que reciben un financiamiento miserable; particulares subvencionados que maximizan sus utilidades estrujando a los profesores con cuarenta y más horas de trabajo en aula. Y universidades, perfectamente acreditadas (¿CÓMO?) en las cuales, mediante la figura de las inmobiliarias, accionistas pueden retirar capital y utilidades; ser compradas y vendidas. En las cuales los alumnos al ingresar deben firmar una renuncia a su legítimo derecho a asociación; o que prácticamente carecen de profesores contratados, y recurren a un proletariado del conocimiento (profesores-taxi) al cual sólo pagan honorarios (nada para previsión social; nada para salud); al que, en algunos casos, contabilizan sólo las horas efectivamente dictadas, sin admitir excepción: si un día te tocaba clase, y hubo terremoto, fiesta nacional, paro del transporte, lo que sea, no se te paga, y punto. Y todo esto, frente a la mirada benévola de las autoridades.
Eduardo Sabrovsky en El mostrador
Tags: Chile, educación, movimiento estudiantil, política, universidadPues él cree que si la verdad tiene una voz —suponiendo que la verdad exista y además pueda hablar—, ésta surgirá de la boca de una mujer
Paul Auster en El libro de la memoria (parte de La invención de la Soledad)
Tags: Literatura, Paul-Auster, verdadSupe entonces, con humildad, con perplejidad, en un arranque de mexicanidad absoluta, que estábamos gobernados por el azar y que en esa tormenta todos nos ahogaríamos, y supe que sólo los más astutos, no yo ciertamente, iban a mantenerse a flote un poco más de tiempo.
Roberto Bolaño, en Los detectives salvajes
Tags: azar, Literatura, roberto bolaño… It’s just pure dumb luck. I don’t believe in destiny. It’s what you might call, or what I call in any case, the mechanics of reality. There’s no meaning to this. It’s absolutely meaningless, and yet this is the way the world works.
Paul Auster en Act of God [trailer]
Tags: ateísmo, azar, dios, mecánica de la realidad, Paul-Auster, religiónOcho gráficos que explican todo lo que está mal con EEUU… o al menos esa es la idea. A todo esto, el gráfico de Chile muy probablemente no sea mucho mejor
Tags: economía, EEUU, política
Ayer recibí La segunda enciclopedia de Tlön, la primera novela steampunk chilena y segunda del fallecido escritor quillotano Sergio Meier... Me pareció una buena opción para leer mientras espero el reemplazo de mi nook.
Conocí a Meier a través de un viejo amigo de la época del colegio. Totalmente recomendable su entrevista en Una Belleza Nueva con Christian Warnken, que se puede ver completa en Otro Canal.
De la presentación del libro:
¿Se imagina al más grande físico de la historia, Isaac Newton, viviendo al interior de una nave estelar regida por ordenadores cuánticos? La Segunda Enciclopedia de Tlön”, la primera novela steampunk chilena, nos invita a viajar por universos holográficos, mundos victorianos y nuestro vecindario. Mientras somos testigos de una lucha que alcanza a inteligencias artificiales, matrices de realidad virtual, corporaciones galácticas e inclusive, la esotérica cábala hebrea. Así, Sergio Meier, un alquimista posmoderno, desencadena su Apocalipsis de alto vuelo épico.
A todo esto, la mejor forma de adquirirla es consultando directamente en el sitio web de su editorial: Puerto de Escape.
Tags: Chile, ciencia ficción, Literatura, steampunkEsto ya tiene algunos días, pero de todos modos va el dato: desde http://www.lalapixiesloveyou.com/ se puede descargar el show de Pixies en Coachella 2004, en MP3 de 320kbps:
A continuación el tracklist completo:
(cc) by-nd *Zephyrance – don’t wake me up.
Tags: arte, Filosofía, fotografía, vida"Mendeley is a free reference manager and academic social network that can help you organize your research, collaborate with others online, and discover the latest research."
Tags: Research reference collaboration tools web2.0 software Bibliography papers
"Spur A fun and easy way to critique your web pages."
Tags: webdesign critique webdev review web design
"The Lost Notebooks of Hank Williams is a studio album by various artists. Country music singer Hank Williams died at age 29 on January 1, 1953. Police officers found in his car along with his body the lyrics for songs yet to be recorded. In 2006, a janitor of Sony/ATV Music Publishing found on a dumpster of the company the notes and tried to sell them to different road shows failing[clarification needed], the unfinished lyrics were later returned to Sony/ATV, which handed them to Bob Dylan in 2008 to complete and record them. Dylan and other artists each recorded a song for the album. The album was released on October 4, 2011."
"Definition of DONE! 10 Point ChecklistA key principle of agile software development is “done means DONE!” To be more specific, here’s a 10 point checklist of what constitutes ‘feature complete’…"
Tags: definition checklist webdesign
"Much has been spoken and written recently about the virtues of craftsmanship in the context of web design and development. It seems that we as fabricators of the web are finally tiring of seeking out parallels between ourselves and architects, and are turning instead to the fabled specialist artisans. Identifying oneself as a craftsman or craftswoman (let’s just say craftsperson from here onward) will likely be a trend of early 2012. In this pre-emptive strike, I’d like to expound on this movement as I feel it pertains to front-end development, and encourage care and understanding of the true qualities of craftsmanship (craftspersonship)."
Tags: webdesign developing css front-end
"In this one hour tutorial Simon Collison will demonstrate why convention, order and understanding are vital to web design and development teams. He’ll give insights into how Erskine approach projects and will help attendees explore ways of creating and evolving their own "Ultimate Package". Why conventions are essential for successful web projects. How Erskine approach HTML, CSS & JavaScript in their own projects. What to consider when developing your own "Ultimate Package"."
Tags: developing css front-end webdev webdesign
Throughout my time writing Javascript code, I've come to realize that while I love the language to bits, it is a little difficult to understand. A lot of people have attributed this to its (admittedly not so great) design, or its obvious deviations from the paths well worn by other languages. Either way, understanding a few simple truths can go a long way with JS. What follows is the condensed and written version of the introductory class on JavaScript that I give at training programs and user groups.
Here are some statistics about the size, number of resources and other such metrics of pages on the world wide web. These are collected from a sample of several billions of pages that are processed as part of Google's crawl and indexing pipeline. In processing these pages, we not only take into account the main HTML of the page, but also discover and process all embedded resources such as images, scripts and stylesheets.
As it happens, designing Future Interfaces For The Future used to be my line of work. I had the opportunity to design with real working prototypes, not green screens and After Effects, so there certainly are some interactions in the video which I'm a little skeptical of, given that I've actually tried them and the animators presumably haven't. But that's not my problem with the video.
Tags: future Design interaction technology
I was hunting for jQuery performance tricks for a while to tune my heavy dynamic web app. After digging in a lot of articles decided to make a list of the best common performance tips. I also built a handy jQuery Performance Cheat Sheet that can be printed or placed on my desktop.
" Como ya sabemos, en la programación orientada a objetos (POO) es habitual tratar con los conceptos de encapsulación, herencia y polimorfismo. Puede que haya autores, y por qué no, también lectores, que tengan sus reservas a la hora de considerar JavaScript como un lenguaje totalmente orientado a objetos. La intención de este artículo no es entrar en este tipo de polémicas, pero lo que sí podemos considerar es que JavaScript, como hemos visto anteriormente, soporta objetos y hace una simulación muy personal de otros conceptos como clases o herencia."
Tags: javascript
"Using directories to group articles by category is a great way to help people to navigate through many articles. At some point, however, someone will want to find all the articles that pertain to a certain topic that may not have a directory of it’s own, or may span many directories . This is what the search engine is for."
In preparation for my upcoming talk on jQuery Templates, I’ve been been deep diving into the jQuery Template plugin created by Microsoft.. Many of you are probably familiar with server-side template engines like Smarty or Cheetah but only recently have client-side template engines taken off. Considering how complex our web apps are becoming, it makes total sense.
Tags: jquery javascript template js
The iPhone 4 features a vastly superior display resolution (614400 pixels) over previous iPhone models, containing quadruple the 153600-pixel display of the iPhone 3GS. The screen is the same physical size, so those extra dots are used for additional detail — twice the detail horizontally, and twice vertically. For developers only using Apple’s user interface elements, most of the work is already done for you.
"By encapsulating data and behavior into a view model, you get a clean, extensible foundation on which to build sophisticated UIs without getting lost in a tangle of event handlers and manual DOM updates."
Tags: javascript framework jquery knockout