Delirios de un Informático

Funciones personalizadas para Less mediante Grunt

Less dispone de muchas funciones nativas, pero hay ocasiones en las que resultaría útil disponer de funciones personalizadas porque los mixins tampoco son suficientes. Por ejemplo, puede ser útil comprobar si existe un archivo, leer su contenido o ejecutar una herramienta externa para obtener los valores.

Para estos casos, es posible añadir nuevas funciones a Less mediante Grunt y el plugin grunt-contrib-less mediante la opción customFunctions, con lo que tendremos toda la potencia de Node.js a nuestra disposición para realizar todo que se nos ocurra.

Este sería el contenido de un Gruntfile.js de ejemplo:

module.exports = function(grunt) {
    grunt.loadNpmTasks('grunt-contrib-less');

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        less: {
            options: {
                customFunctions: require('./functions.js'),
                sourceMap: false
            },
            build: {
                src: 'test.less',
                dest: 'test.css'
            }
        }
    });

    grunt.registerTask('default', ['less']);
};

Como se puede ver, utilizo un require('./functions.js') para almacenar en un archivo todas las funciones, que deben exportarse del siguiente modo:

exports.test = function(less, arg1, arg2) {
    // código personalizado
}

Cada función se exporta con un nombre que será el utilizado en Less:

body {
  background-color: test('test.jpg', #FFFFFF);
}

Hay que tener en cuenta los siguientes aspectos:

  • El primer argumento recibido por la función es una instancia del compilador Less
  • El resto de argumentos son los que se especifiquen en Less
  • Cada argumento es un objeto con las siguientes propiedades (entre otras):
    • value: valor especificado en Less
    • quote: entrecomillado usado para convertir el valor
    • escaped: indica si se aplicarán caracteres de escape en el valor
  • Cualquiera de las propiedades puede modificarse para que el compilador las utilice
  • El entrecomillado será el especificado en Less: ‘, ” o ninguno si se usa un color o cualquier otro valor CSS
  • El valor de retorno de la función puede ser un objeto como el recibido como argumento o una cadena que se mostrará tal cual

El único problema que no he logrado solventar es poder acceder a las variables definidas en el punto en el que se llama a la función. Sería muy útil poder acceder a las variables, añadirlas y modificarlas, pero por lo que he podido comprobar la instancia de Less recibida por la función no da acceso a ellas.

Dash & Zeal: navegadores de documentación para programadores

Dash (para Mac OS X) y Zeal (Windows y Linux) son dos programas imprescindibles para cualquier programador: unifican en una única interfaz la documentación de más de 100 lenguajes, frameworks, librerías y diverso software. Los docsets se actualizan automáticamente y disponen de integración con todo tipo de editores.

Cómo conectar PHP a SQL Server en Mac OS X

Siguiendo con mi serie de anotaciones sobre el desarrollo con PHP en Mac OS X, hoy toca hablar de algo que es más sencillo de lo que parece a primera vista: conectar PHP con SQL Server (virtualizado en una máquina Windows Server 2003 en mi caso) utilizando iODBC en Mac OS X Lion.

Con la versión de PHP que trae Lion de serie viene incluído el soporte para iODBC (una implementación de código abierto de ODBC y alternativa a unixODBC), al que le basta un controlador compatible para acceder a cualquier servidor de bases de datos. En este caso se recurre a FreeTDS, la implementeación de código abierto del controlador para SQL Server.

Como para muchas otras aplicaciones que se necesitan compilar en Mac OS X, he recurrido a Homebrew, que tras instalarlo sólo hay que ejecutar lo siguiente:

brew install freetds

La configuración también resulta sencilla: el archivo /usr/local/etc/freetds.conf debe contener lo siguiente al final:

[sqlserver]
	host = ip_o_host_del_servidor
	port = 1433
	tds version = 7.1

Luego, hay que crear el archivo /etc/odbcinst.ini con el siguiente contenido:

[FreeTDS]
Description = FreeTDS
Driver = /usr/local/lib/libtdsodbc.so
Setup = /usr/local/lib/libtdsodbc.so
UsageCount = 1

Por último, debe definirse el DSN creando el archivo /etc/odbc.ini:

[ejemplo]
Driver = FreeTDS
Database = ejemplo
Description = Base de datos de ejemplo
ServerName = sqlserver

Tras estos pasos, PHP debería poder conectarse al servidor SQL Server sin ningún problema. Pueden usarse las funciones ODBC de PHP para realizar la conexión:

$db = odbc_connect('ejemplo', 'usuario', 'contraseña');
$result = odbc_exec($db, "SELECT campo1, campo2 FROM tabla");
while($row = odbc_fetch_object($result)) var_dump($row);
odbc_close($db);

Si existe cualquier problema con la conexión, puede instalarse unixODBC con Homebrew (brew install unixodbc) y testear la conexión y obtener mensajes de error con el siguiente comando:

tsql -S ip_o_host_del_servidor -U sa

Por último es importante no añadir espacios o tabulaciones en los archivos .ini o iODBC no podrá obtener correctamente los valores causando un error en la conexión.

Code Igniter Reactor 2.0.0 y la línea de comandos

Una de las novedades de Code Igniter 2.0 es la incorporación de compatibilidad para su uso a través de la línea de comandos (antes había que recurrir a chapuzas). Se añade un intérprete que permite llamar a los métodos de los controladores a través de los parámetros de un script. Para eso, hay que definir el siguiente elemento en la configuración:

$config['uri_protocol'] = 'CLI';.

De este modo podremos realizar una llamada del tipo ./cli.php controlador parametro1 parametro2, lo que equivaldría a una dirección web como http://host/controlador/parametro1/parametro2. Mi recomendación es que el script ejecutado sea una copia del index.php en donde se añada la citada configuración (utilizando la nueva variable $assign_to_config), así como un #!/usr/bin/php -q en la primera línea para facilitar la ejecución directa.

Una vez dentro del código puede detectarse si la ejecución se realiza a través de línea de comandos simplemente determinando si se ha definido la constante STDIN, así como con la comprobación del elemento uri_protocol de la configuración de Code Igniter.

Por otro lado, puede ser necesario determinar quién está ejecutando el script para otorgar o no privilegios. Eso puede hacerse gracias a la variable superglobal $_ENV, en donde se define el elemento USERNAME. Por ejemplo, para comprobar si el script se ejecuta con privilegios de administrador (bien siendo root o mediante sudo) basta con el siguiente codigo:

$auth = (getenv('USERNAME') == 'root');

Actualizando a Code Igniter Reactor 2.0.0

Hace poco que se lanzó Code Igniter Reactor 2.0.0 con importantes novedades. Los chicos de EllisLab han publicado un changelog completo pero hay algunos detalles que no han agregado al proceso de migración:

  • Core libraries: si habías extendido las librerías CI_Loader o CI_Output deberás crear una carpeta llamada core y moverlas ahí, ya que en esta nueva versión estas librerías se separan de las librerías estándar
  • Ordenación de resultados en Active Record: se han cargado el método orderby() de Active Record para sustituirlo por order_by(), por lo que habrá que realizar el cambio para que funcionen las consultas (Regexxer es una excelente herramienta para estas tareas)
  • Traducciones: podían haber aprovechado para indicar que se ha creado un repositorio de traducciones de donde se pueden descargar ya

El resto de cambios están documentados y no suponen demasiado problema, por eso me encanta Code Igniter :).