dev/Desarrollo de bloques

(Redirigido desde «Desarrollo de bloques»)
Saltar a: navegación, buscar

Nota: Esta es una traducción de una página de la documentación para desarrolladores (Developer docs), que se considera particularmente importante, y que en su versión original se actualiza frecuentemente. Por ello, se le recomienda que revise la página original en idioma inglés: Blocks.

Moodle 1.9

Autor: Jon Papaioannou (pj@uom.gr)</div>

Traducción: Astrid Sánchez (astrid@solearning.com)

Versión: $Id: HOWTO.html,v 1.10 2005/02/11 06:30:49 defacer Exp $</div> </div>

Contenido

Una guía paso-a-paso para crear bloques

Resúmen

El presente documento sirve como guía a los desarrolladores que quieren crear sus propios bloques para usar en Moodle. Aplica solamente a la versión en desarrollo 1.5 de Moodle (y cualquiera más reciente), ya que el subsistema de bloques fue re-escrito y expandido. Sin embargo, también la puedes encontrar útil si quieres modificar los bloques escritos para Moodle 1.3 o 1.4 de modo que funcionen con las últimas versiones. (Ver Apéndice B).

La guía está escrita como un curso interactivo el cuál apunta al desarrollo de un bloque configurable, multipropósito que despliega HTML arbitrario. Está dirigida principalmente a personas con poca experiencia con Moodle o en programación en general y pretende mostrar que tan fácil es crear nuevos bloques para Moodle. A pesar de esto se requieren unos conocimientos básicos en programación PHP. Desarrolladores experimentados y aquellos que solo quieren un texto de referencia deberían referirse al Apéndice A, porque el contenido central es más bien sencillo.

Conceptos básicos

A través de esta guía, seguiremos la creación de un bloque "HTML" desde cero con el objeto de demostrar la mayoría de las características del bloque que tenemos a nuestra disposición. Nuestro bloque se llamará "SimpleHTML". No es necesario que recordemos el nombre del directorio real en el servidor donde se guardarán los archivos de nuestro bloque, pero por consistencia seguiremos la práctica de usar la forma en minúscula "simplehtml" en cualquier caso donde tal nombre se necesite. Cuando nos referimos a un archivo o al nombre de un directorio que contiene "simplehtml", es importante recordar que solo cambiaremos la parte "simplehtml"; el resto es estandarizado y esencial para que Moodle funcione correctamente.

Cuando en esta guía se mencione la ruta de un archivo, siempre comenzará con un slash (/). Esto se refiere al directorio home de Moodle; todos los archivos y directorios serán referidos con respecto a este directorio.

En sus marcas, listos, ¡Fuera!

Para definir un "bloque" en Moodle, en el caso más básico solo necesitamos un archivo de código fuente. Comenzamos por crear el directorio /blocks/simplehtml/ y un archivo llamado /blocks/simplehtml/block_simplehtml.php el cual contendrá nuestro código. Entonces comenzamos a codificar el bloque:

class block_simplehtml extends block_base {
    function init() {
        $this->title = get_string('simplehtml', 'block_simplehtml');
        $this->version = 2004111200;
    }
}

La primera línea es la definición de nuestra clase bloque; debe nombrarse exactamente de la manera mostrada. De nuevo, solo la parte "simplehtml" puede (en realidad debe) ser cambiada; todo lo demás está estandarizado.

A nuestra clase se le da entonces un pequeño método: init. Este es esencial para todos los bloques, y su propósito es definir las dos variables miembros de la clase listados en ella. Pero, ¿qué significan realmente estos valores? Aquí hay una descripción más detallada.

$this->title es el título que aparece en la cabecera de nuestro bloque. Podemos poner lo que queramos; en este caso está definido para que lea el título real de un archivo de lenguaje que presumiblemente estamos distribuyendo con el bloque. Saltaré un poco adelante aquí y diré que si quieres que tu bloque no muestre absolutamente ningún título, entonces debes poner cualquier valor descriptivo que quieras (pero no lo dejes vacío). Más adelante veremos como deshabilitar el despliegue del título.

$this->version es la versión de nuestro bloque. Realmente haría alguna diferencia solo si queremos que nuestro bloque guarde sus propios datos en tablas especiales en la base de datos (esto es, para bloque muy complejos). En este caso el número de la versión es usada exactamente como se usa en las actividades; un script de actualización lo usa para incrementalmente actualizar una versión "vieja" de los datos del bloque a los más recientes. Bosquejaremos este proceso más adelante, ya que los bloques tienden a ser relativamente simples y no mantienen sus propios datos privados. Ciertamente este es el caso de nuestro ejemplo, así que solo definiremos $this->version como YYYYMMDD00 y nos olvidamos de esto.

ACTUALIZANDO: Antes de la versión 1.5, la estructura básica de cada clase bloque era ligeramente diferente. Vaya al Apéndice B para más información acerca de los cambios que los bloques viejos tienen que hacer para estar conforme al nuevo estándar.

Acabo de escuchar estático

Con el fin de que nuestro bloque realmente muestre algo en pantalla, necesitamos agregar un método más a nuestra clase (antes del corchete de cierre final en nuestro archivo). El nuevo código es:

function get_content() {
    if ($this->content !== NULL) {
        return $this->content;
    }

    $this->content = new stdClass;
    $this->content->text = '¡El contenido de nuestro bloque SimpleHTML!';
    $this->content->footer = 'Pie de página aquí...';

    return $this->content;
}

No podría ser más simple, ¿verdad?, Vamos a examinar este método para ver que está pasando Primero que todo, hay un chequeo que retorna el valor actual de $this->content si no es NULL; de otra manera procedemos a "calcularlo". Dado que este cálculo es una operación potencialmente consumidora de tiempo y será llamada varias veces por cada bloque (Moodle trabaja de esa manera internamente) tomamos una precaución e incluimos este ahorrador de tiempo.

Suponiendo que el contenido no ha sido calculado antes (este era NULL), entonces lo definimos desde cero. El código habla por si mismo aquí, así que no hay mucho por decir. Solo ten presente que podemos usar HTML en ambos el texto y el pie de página, si queremos.

En este punto nuestro bloque debería poder de ser instalado automáticamente en Moodle y agregarse a cursos; visita tu página de administración para instalarlo y después de verlo en acción regresa a nuestro tutorial (N. del T. La página de administración depende de donde tengas instalado tu Moodle, generalmente ''http://host/moodle/admin'')

Configúralo

La versión actual de nuestro bloque no hace mucho en realidad; solo muestra un mensaje fijo, lo cual no es muy útil. Lo que realmente queremos hacer es permitirle a los profesores configurar lo que hay en el bloque. Esto, en lenguaje de bloque, se llama "configuración de instancias". Así que vamos a darle a nuestro bloque una configuración de instancia...

Primero que todo, necesitamos decirle a Moodle que queremos que le de a nuestro bloque opciones de configuración de instancia específica. Es tan simple como agregar un método más a nuestra clase bloque:

function instance_allow_config() {
    return true;
}

Este pequeño cambio es suficiente para hacer que Moodle muestre un icono de "Edit " en la cabecera de nuestro bloque cuando entramos en modo edición de cualquier curso. Sin embargo, si tratas de dar click en este icono se te presentará una nota que se queja diciendo que la configuración no ha sido implementada correctamente. Inténtalo, es inofensivo.

La queja de Moodle tiene sentido. Le dijimos que queremos configurar, pero no le dijimos qué tipo de configuración queremos, o como debe ser mostrada. Para hacerlo, necesitamos crear un archivo más: /blocks/simplehtml/config_instance.html (el cual tiene que estar nombrado exactamente así). Por el momento, copia y pega lo siguiente en él y guárdalo:

 <table cellpadding="9" cellspacing="0">
 <tr valign="top">
     <td align="right">
         <?php print_string('configcontent', 'block_simplehtml'); ?>:
     </td>
     <td>
         <?php print_textarea(true, 10, 50, 0, 0, 'text', $this->config->text); ?>
     </td>
 </tr>
 <tr>
     <td colspan="2" align="center">
         <input type="submit" value="<?php print_string('savechanges') ?>" />
     </td>
 </tr>
 </table>
 <?php use_html_editor(); ?>
 

No es difícil ver que el código de arriba solo nos dará un área de texto con un editor wysiwyg habilitado para escribir el contenido deseado de nuestro bloque en él y un botón de envio para grabar (N. del T. "submit", envío de un formulario; Un editor "wysiwyg" - What You See Is What You Get - es en el que "Lo que ves es lo que obtienes", como muchos de los procesadores de texto conocidos, que permiten modificaciones de fuente, colores, etc.). Pero... ¿qué es $this->config->text? Bien... Moodle vas más allá haciéndole las cosas más fáciles a los desarrolladores de bloques. ¿Notaste que el área de texto se llama realmente "text"? Cuando se presiona el botón submit, Moodle guarda todos y cada uno de los campos que pueda encontrar en nuestro archivo config_instance.html como datos de configuración de instancia. Podemos ahora acceder a estos datos como $this->config->nombredevariable, donde nombredevariable es el nombre real que usamos para nuestro campo; en este caso "text". Así en esencia, el formulario anterior solo muestra en el área de texto el contenido actual del bloque (como en realidad debería ser) y entonces nos permite cambiarlo.

También podrás sorprenderte por la presencia de un botón de enviar y al mismo tiempo la ausencia de cualquier elemento <form>. Pero la verdad es que, no necesitamos preocuparnos acerca de esto para nada; ¡Moodle realmente va mas allá haciéndole las cosas más fáciles a los desarrolladores! Solo imprimimos las opciones de configuración que nosotros queremos, en cualquier formato que nosotros queramos; incluyendo un botón enviar, y Moodle manejará el resto por sí mismo. Las variables de configuración de instancias están a nuestra disposición para accederlas desde cualquier método de la clase excepto init.

En el caso de que el comportamiento por defecto no sea satisfactorio, todavía podemos reconfigurarlo. Sin embargo, esto requiere modificaciones avanzadas a nuestra clase bloque y no se cubrirá aquí; vaya al [#appendix_a Apéndice A] para más detalles.

Ahora que tenemos la habilidad de referirnos a estos datos de configuración de instancias a través de $this->config, el truco final es decirle a nuestro bloque que muestre realmente lo que se ha guardado en su configuración. Para hacer esto, encuentra esta parte en /blocks/simplehtml/block_simplehtml.php:

$this->content = new stdClass;
$this->content->text = '¡El contenido de nuestro bloque SimpleHTML!';
$this->content->footer = 'Pie de página aquí...';

y cambiala por:

$this->content = new stdClass;
$this->content->text = $this->config->text;
$this->content->footer = 'Pie de página aquí...';

Ah, y dado que el pie de página no es realmente excitante en este punto, lo removemos de nuestro bloque porque no está contribuyendo en nada. Fácilmente podríamos haber decidido hacer configurable también al pie de página de la manera anterior. Ahora en nuestro código más actualizado, esta parte sería:

$this->content = new stdClass;
$this->content->text = $this->config->text;
$this->content->footer = ;

Después de esta discusión, ¡nuestro bloque está listo para exhibirse!. En realidad, si visitas ahora cualquier curso con un bloque SimpleHTML, verás que modificar su contenido es ahora tan fácil como un chasquido.

El especialista

Implementar la configuración de instancia para el contenido del bloque fue bueno para estimular nuestro apetito, pero ¿quién quiere detenerse aquí? ¿Por qué no configurar también el título del bloque? Por qué no, ciertamente. Bien, nuestro primer intento para lograrlo es bastante natural: Vamos a agregar otro campo a /blocks/simplehtml/config_instance.html. Aquí va:

 <tr valign="top">
     <td align="right"><p><?php print_string('configtitle', 'block_simplehtml'); ?>:</td>
     <td><input type="text" name="title" size="30" value="<?php echo $this->config->title; ?>" /></td>
 </tr>

Guardamos el archivo editado, vamos a un curso, editamos el título del bloque y ¡nada pasa! La configuración de la instancia está guardada correctamente, todo está bien (editarlo una vez más lo comprueba) pero no se está desplegando. Todo lo que tenemos es el simple título "SimpleHTML". Esto no es tan raro, si pensamos un poco atrás. ¿Recuerdas ese método init, donde definimos $this->title? Realmente no hemos cambiado su valor desde entonces, y $this->title definitivamente no es el mismo $this->config->title (al menos para Moodle). Los que necesitamos es un modo de actualizar $this->title con el valor en la configuración de la instancia. Pero como dijimos hace poco, podemos usar $this->config en todos los métodos ¡excepto en init! Entonces ¿qué podemos hacer?

Vamos a sacar otro as bajo la manga, y agregar este pequeño método a nuestra clase bloque:

function specialization() {
    $this->title = $this->config->title;
}

¡Ajá, aquí está lo que hemos querido hacer desde el principio! ¿Pero que pasa con el método specialization?

Este método "mágico" tiene en realidad un propiedad muy interesante: se garantiza que es llamado automáticamente por Moodle tan pronto como la configuración de nuestra instancia está cargada y disponible (esto es, inmediatamente después de que se llama init). Es decir antes de que el contenido del bloque sea calculado por primera vez, y por cierto antes de que cualquier otra cosa sea hecha con nuestro bloque. De este modo, poner un método specialization es la elección natural para cualquier configuración que necesita ser realizada "tan rápido como sea posible", como en este caso.

Ahora me ves, ahora no me ves

Este sería un buen momento para mencionar otra elegante técnica que puede ser usada en los bloques, y la cual se aplica muy a menudo. Específicamente puede ser el caso en que nuestro bloque tenga algo interesante que mostrar en algún momento; pero en otros casos, no tenga nada útil que decir. (Un ejemplo aquí sería el bloque "Actividades recientes", cuando no hayan actividades recientes. Sin embargo en ese caso el bloque escoge informarte explícitamente de la falta de actividades, lo cuál es razonablemente útil). Sería bueno, entonces que nuestro bloque "desapareciera" si no hay necesidad de mostrarlo.

Ciertamente esto es posible, y la manera de hacerlo es asegurarse de que después de que el método get_content es llamado, el bloque está completamente desprovisto de contenido. Específicamente, "desprovisto de contenido" significa que tanto $this->content->text como $this->content->footer son iguales al string vacío ("). Moodle hace este chequeo llamando al método is_empty, y si el bloque está realmente vacío entonces no se mostrará en lo absoluto.

Nota que el valor exacto del título del bloque y la presencia o ausencia de un método hide_header no afecta este comportamiento. Un bloque es considerado vacío si no tiene contenido, sin importar nada más.

Somos legión

Ahora mismo nuestro bloque es completamente configurable, tanto en el título como en el contenido. Es tan versátil, de hecho, que podríamos hacer casi cualquier cosa de él. Sería muy agradable poder agregar múltiples bloques de este tipo en un curso. Y, como puedes haber adivinado, hacerlo es tan simple como agregar otro pequeño método a nuestra clase bloque:

function instance_allow_multiple() {
    return true;
}

Esto le dice a Moodle que debería permitir cualquier cantidad de instancias del bloque SimpleHTML en cualquier curso. ¡Después de grabar los cambios en nuestro archivo, Moodle nos permite agregar múltiples copias del bloque a un curso inmediatamente sin más!

Hay un par de puntos interesantes más para notar aquí. Primero que todo, incluso si un bloque permite múltiples instancias en la misma página, el administrador todavía tiene la opción de deshabilitar tal comportamiento. Esto puede ser definido para cada bloque desde la página Administration/Configuration/Blocks.

Y finalmente, un bonito detalle es que tan pronto como definimos un método instance_allow_multiple, el método instance_allow_config que ya estaba definido se vuelve obsoleto. Moodle asume que si un bloque permite múltiples instancias de sí mismo, estas instancias querrán ser configuradas (¿Qué sentido tienen múltiples instancias iguales en la misma página si son idénticas?) y automáticamente les da un icono de "Edit". Así, podemos remover todo el método instance_allow_config sin ningún daño. Solo lo necesitaremos cuando no se permiten múltiples instancias del bloque.

Los efectos de la globalización

Configurar cada instancia del bloque con sus propios datos personales, es bastante bueno, pero algunas veces los administradores necesitan alguna manera de "tocar" todas las instancias de un bloque específico a la vez. En el caso de nuestro bloque SimpleHTML, algunas configuraciones que tendrían sentido aplicar a todas las instancias no son tan difíciles de encontrar. Por ejemplo, podríamos querer limitar el contenido de cada bloque para solo tantos caracteres, o podríamos tener una configuración que filtre el HTML del contenido del bloque, permitiendo solo texto puro en él. Grandioso, tal característica no hará que nos ganemos un premio por nombrar nuestro bloque "SimpleHTML" pero algún administrador atormentado en alguna parte podría encontrarlo realmente útil.

Este tipo de configuración se llama "configuración global" y aplica solo a un tipo de bloque específico (sin embargo, todas las instancias de ese tipo de bloque son afectadas). Implementar tal configuración para nuestro bloque es bastante similar a implementar la configuración de instancia. Veremos ahora la implementación del segundo ejemplo, teniendo una configuración que solo permite texto y no HTML en el contenido del bloque.

Primero que todo, necesitamos decirle a Moodle que queremos que nuestro bloque tenga una configuración global, qué sorpresa, agregando un pequeño método a nuestra clase bloque:

function has_config() {
    return true;
}

Entonces, necesitamos crear un archivo HTML que realmente muestre la pantalla de configuración. En nuestro caso, solo mostraremos una caja de selección (N. del T. "checkbox") que diga "No permitir HTML en el contenido" (N. del T. "Do not allow HTML in the content") y un botón de "Enviar" (N. del T. "submit") . Vamos a crear el archivo /blocks/simplehtml/config_global.html el cuál otra vez debe ser nombrado tal cual, y copia y pega lo siguiente dentro él:

 <div style="text-align: center;">
 <input type="hidden" name="block_simplehtml_strict" value="0" />
 <input type="checkbox" name="block_simplehtml_strict" value="1" 
   <?php if(!empty($CFG->block_simplehtml_strict)) echo 'checked="checked"'; ?> />
 <?php print_string('donotallowhtml', 'block_simplehtml'); ?>
 <p><input type="submit" value="<?php print_string('savechanges'); ?>" /></p>
 </div>

La verdad en el nombre de nuestro bloque, luce bastante simple. Lo que hace es mostrar una caja de selección llamada block_simplehtml_strict y si la variable de configuración de Moodle con el mismo nombre (esto es, $CFG->block_simplehtml_strict) existe y no esta vacía (lo que significa si no es igual a un string vacío, a cero, o a un falso booleano) muestra la opción pre-seleccionada (reflejando el estado actual). ¿Por qué seleccionamos la configuración con el mismo nombre? Porque la implementación por defecto de la configuración global toma todas las variables que tenemos en nuestro formulario y las guarda como opciones de configuración en Moodle con el mismo nombre. Así, es buena práctica usar un nombre descriptivo y también uno que no tenga la posibilidad de tener conflictos con otra configuración. block_simplehtml_strict claramente satisface los dos requerimientos.

El lector astuto puede haber notado que en realidad tenemos dos campos de entrada llamados block_simplehtml_strict en nuestro archivo de configuración. Uno está escondido y su valor es siempre 0; el otro es la caja de selección y su valor es 1. ¿Que pasa? ¿Porqúe tenerlos a los dos ahí? Realmente, esto es un pequeño truco para hacer nuestro trabajo tan simple como sea posible. Los formularios HTML trabajan de esta manera: Si una caja de selección en un formulario no esta seleccionada, su nombre no aparece para nada en las variables que se le pasan a PHP cuando el formulario es enviado. Esto efectivamente significa que, cuando deseleccionemos una caja y hagamos clic en enviar, la variable no se le pasa a PHP en lo absoluto. Así PHP no sabrá que debe actualizar su valor a "0", y nuestra configuración "strict" no podrá ser desactivada de ninguna forma después de que la activamos por primera vez. Definitivamente no es el comportamiento que deseamos.

Sin embargo, cuando PHP maneja las variables recibidas de un formulario, son procesadas en el orden en que aparecen en el formulario. Si una variable aparece teniendo el mismo nombre que una variable ya procesada, el nuevo valor sobrescribe el antiguo. Aprovechando esto, nuestra lógica es la siguiente: La variable block_simplehtml_strict es puesta primero incondicionalmente en "0". Entonces, si la caja es seleccionada, es puesta en "1", sobrescribiendo el valor previo como se dijo. El resultado neto es que nuestra configuración funciona como debería.

Para redondear nuestra bolsa de trucos, note que el uso de if(!empty($CFG->block_simplehtml_strict)) en la prueba para "¿debería estar la caja seleccionada por defecto?" es bastante deliberado. La primera vez que se corre el script, la variable $CFG->block_simplehtml_strict no existirá para nada. Después de que este puesta por primera vez, su valor puede ser "0" ó "1". Dado que ambos "no seleccionado" (N. del T. nulo) y el string "0" son evaluados como vacío mientras que el string "1" no, nos las hemos arreglado para evitar cualquier advertencia de PHP considerando la variable vacía, y tendremos una agradable y humana representación para sus dos posibles valores ("0" y "1").

Ahora que nos las hemos arreglado para introducir una cantidad respetable de trucos en unas pocas líneas de HTML, podemos discutir también una alternativa en caso de que los trucos no sean suficientes para la configuración específica que tenemos en mente. El método config_save guarda los datos, y su implementación por defecto es como sigue:

function config_save($data) {
    // Comportamiento por defecto: graba todas las variables como propiedades $CFG
    foreach ($data as $name => $value) {
        set_config($name, $value);
    }
    return true;
}

Como se ve claramente, Moodle le pasa a este método un arreglo asociativo $data el cual contiene todas las variables que vienen de nuestra pantalla de configuración. Si queremos hacer el trabajo sin el truco de "esconder la variable con el mismo nombre" que usamos arriba, un modo de hacerlo sería sobrescribiendo este método como sigue:

function config_save($data) {
    if(isset($data['block_simplehtml_strict'])) {
        set_config('block_simplehtml_strict', '1');
    }
    else {
        set_config('block_simplehtml_strict', '0');
    }
    return true;
}

Bastante directo: si se nos pasa la variable "block_simplehtml_strict", entonces solo puede significar que el usuario la ha seleccionado, así que ponemos la variable de configuración con el mismo nombre en "1". De otra manera, la ponemos en "0". Por supuesto esta versión necesitaría ser actualizada si agregamos más opciones de configuración porque no responde a ellas como lo hace la implementación por defecto. Aún así, es útil saber como podemos sobrescribir la configuración por defecto si esta no llena nuestras necesidades (por ejemplo, podemos no querer guardar las variables como parte de la configuración de Moodle sino hacer otra cosa con ellas).

Así, ahora estamos en el punto donde sabemos si el bloque debe permitir etiquetas HTML en su contenido o no. ¿Como hacemos que el bloque realmente respete esta configuarción? Podríamos decidir hacer una de estas cosas: ya sea tener nuestro bloque "limpio" de HTML desde la entrada antes de guardarlo en la configuración de la instancia y entonces mostrarlo tal cual (el acercamiento "impaciente"); o guardar los datos "tal cual" y entonces limpiarlos cada vez justo antes de mostrarlos (el acercamiento "perezoso"). El acercamiento impaciente involucra hacer el trabajo una vez cuando se guarda la configuración; el acercamiento perezoso implica hacer el trabajo cada vez que el bloque se muestra y así apunta a tener un peor desempeño. Desde aquí iremos con el acercamiento impaciente.

Tal como hicimos antes al sobrescribir config_save, lo que necesitamos aquí es sobrescribir el método instance_config_save el cual maneja la configuración de instancia. La implementación por defecto es como sigue:

function instance_config_save($data) {
    $data = stripslashes_recursive($data);
    $this->config = $data;
    return set_field('block_instance', 'configdata', base64_encode(serialize($data)), 
                     'id', $this->instance->id);
}

Esto puede parecer intimidante al principio (¿Qué es todo eso de stripslashes_recursive() y base64_encode() y serialize()?) pero no desfallezcas; no tenemos que tocar ninguna de estas. Solo agregaremos algún código extra de validación al principio y entonces le ordenaremos a Moodle que adicionalmente llame esta implementación por defecto para hacer el almacenamiento real de los datos. Específicamente, agregaremos un método a nuestra clase el cual irá como este:

function instance_config_save($data) {
    // Limpia los datos si tenemos que hacerlo
    global $CFG;
    if(!empty($CFG->block_simplehtml_strict)) {
        $data['text'] = strip_tags($data['text']);
    }
    
    // Y ahora remite a la implementación por defecto definida en la clase padre
    return parent::instance_config_save($data);
}

¡Finalmente! ¡Ahora el administrador tiene el poder absoluto de la vida y la muerte sobre que tipo de contenido está permitido en nuestro bloque "SimpleHTML"! ¿Absoluto? Bien... no exactamente. De hecho, si lo pensamos un momento, se hará evidente que si en algún punto en el tiempo se permite HTML y algunos bloques han guardado su contenido con HTML, y el administrador cambia la configuración a "off", esta solo evitara que los subsecuentes cambios incluyan HTML. Los bloques que ya tengan HTML en su contenido ¡continuarán mostradolo!

Siguiendo esa línea de pensamiento, nuestra próxima parada es darse cuenta de que no tendríamos este problema si hubiéramos escogido el acercamiento perezoso hace un momento, porque en ese caso hubiéramos "higienizado" (N. del T. filtrado, limpiado) cada contenido del bloque justo antes de que este fuera mostrado. La única cosa que podemos hacer con la aproximación impaciente es quitar todas las etiquetas del contenido de todas las instancias SimpleHTML tan pronto como el administrador ponga "HTML off"; pero incluso entonces, poniendo de nuevo "HTML on" no traerá de regreso las etiquetas que quitamos. Del otro lado, la aproximación perezosa puede ser más lenta, pero es más versátil; podemos escoger si quitar o conservar el HTML antes de mostrar el contenido, y no lo perdemos para nada si el administrador cambia de off y on de nuevo. ¿No es la vida de un desarrollador simple y maravillosa? Vamos a dejar esta parte del tutorial con el obligatorio ejercicio para el lector: con el fin de tener el bloque SimpleHTML funcionando "correctamente", encuentra como fortalecer el acercamiento impaciente para quitar todas las etiquetas de la configuración existente de todas las instancias de nuestro bloque, o regresa e implementa el acercamiento perezoso. (Pista: hazlo en el método esarrollo de bloques#get_content|get_content]])

ACTUALIZANDO: Antes de la versión 1.5, el archivo config_global.html se llamaba simplemente config.html. También, los métodos config_save y config_print se llamaban handle_config y print_config respectivamente. Mejorar un bloque para que funcione con Moodle 1.5 implica actualizar estos aspectos; vea el Apéndice B para más información.

Apariencia bonita

Nuestro bloque es ahora completamente funcional, así que vamos a ver ahora algunos de los trucos que podemos usar para hacer su comportamiento personalizado en maneras un poco más útiles.

Primero que todo, hay un par de maneras en que podemos ajustar el aspecto visual de nuestro bloque. Para comenzar, puede ser útil crear un bloque que no muestre cabecera (título) en lo absoluto. Puedes ver este efecto en acción en el bloque Descripción del curso que viene con Moodle. Este comportamiento es logrado, lo adivinaste, agregando un método más a nuestra clase bloque:

function hide_header() {
    return true;
}

Una nota más aquí: no podemos simplemente poner un título vacío en el método del bloque init; es necesario que cada bloque tenga un título único, no vacío después de que se llama init tal que Moodle pueda usarlos para diferenciar entre todos los bloques instalados.

Otro ajuste que podemos querer hacer es ordenarle a nuestro bloque que tome un cierto ancho en la pantalla. Moodle maneja esto como un proceso de dos partes: primero, le pregunta a cada bloque por su ancho preferido y toma el número máximo como el valor deseado. Entonces, la página que esta siendo mostrada puede escoger usar este valor o, más probablemente, acomodarlo en algún rango específico de valores si no lo está ya. Esto significa que la configuración del ancho es un convenio del mejor-resultado; tu bloque puede pedir un cierto ancho y Moodle tratará de dárselo, pero no hay garantía de lo que sea el resultado final. Como ejemplo concreto, todos los formatos estándar de un curso de Moodle entregan cualquier pedido de ancho entre 180 y 210 píxeles, inclusive.

Para decirle a Moodle nuestro ancho de bloque preferido, agregamos un método más a nuestra clase bloque:

function preferred_width() {
    // El valor preferido está en pixeles
    return 200;
}

Esto hará a nuestro bloque (y todos los otros bloques mostrados en el mismo lado de la página) un poco más anchos que lo estándar.

Finalmente, podemos afectar también algunas propiedades del HTML que será usado para imprimir nuestro bloque. Cada bloque está contenido en un elemento <table>, dentro del cual está todo el HTML para ese bloque. Podemos ordenarle a Moodle que agregue atributos HTML con valores específicos a ese contenedor. Esto será hecho para a) afectar directamente el resultado final (si decimos, assign bgcolor="black"), o b) darnos la libertad de personalizar el resultado final usando CSS (de hecho este es el comportamiento por defecto como veremos mas adelante).

En nuestro caso el comportamiento por defecto de esta característica le asignará a nuestro contenedor de bloque el atributo HTML de clase con el valor "sideblock block_simplehtml" (el prefijo "block_" seguido por el nombre de nuestro bloque, en minúscula). Podemos usar entonces esta clase para hacer selectores CSS en nuestro tema para alterar el estilo visual de nuestro bloque (por ejemplo, ".sideblock.block_simplehtml { border:1px black solid}").

Para cambiar el comportamiento por defecto, necesitaremos definir un método el cual retorne un arreglo asociativo de nombres de atributo y valores. Por ejemplo la versión

function html_attributes() {
    return array(
        'class'       => 'sideblock block_'. $this->name(),
        'onmouseover' => 'alert("Mouseover on our block!");'
    );
}

resultará en un evento mouseover agregado a nuestro bloque usando JavaScript, tal como si hubiéramos escrito la parte onfiltered="alert(...)" nosotros mismos en HTML. Nota que realmente duplicamos la parte donde se define el atributo clase (queremos conservar eso, y puesto que sobrescribimos el comportamiento por defecto es nuestra responsabilidad emularlo si es requerido). Y el elegante toque final es que no definamos la clase al valor "block_simplehtml" en el código sino que en vez de eso usemos el método name para hacer que concuerde dinámicamente con el nombre de nuestro bloque.

Solo personal autorizado

No es difícil imaginar un bloque que es muy útil en ciertas circunstancias pero que simplemente puede no tener sentido en otras. Un ejemplo podría ser el bloque "Actividades sociales" el cual es ciertamente útil en un curso con el formato social, pero no es nada útil en un curso con el formato de semanas. Debería haber alguna manera de permitir el uso de tales bloques solo cuando sean en realidad significativos, y no confundir a los usuarios si no lo son.

Moodle nos permite declarar en cuales formatos de curso se le permite a cada bloque ser mostrado, y siempre impone estas restricciones como fueron definidas por los desarrolladores del bloque. La información es dada a Moodle como un arreglo asociativo estándar, con cada clave correspondiendo a un formato de página y definiendo un valor booleano (verdadero/falso) que declara si al bloque debería serle permitido aparecer en este formato de página.

Note el uso deliberado del término página en vez de curso en el párrafo anterior. Esto es porque en Moodle 1.5 y en adelante, los bloques pueden ser mostrados en cualquier página que los soporte. El mejor ejemplo de tales páginas son las páginas de curso, pero no estamos restringidos a ellas. Por ejemplo, la página de vista de quiz (la primera que vemos cuando hacemos click en el nombre del quiz) también soporta bloques.

Los nombres de formato que podemos usar se derivan del nombre del script que es usado realmente para mostrar esa página. Por ejemplo, cuando estamos viendo un curso, el script es /course/view.php (esto es evidente por la línea de dirección del browser). Así, el nombre del formato de esa página es course-view. Se sigue fácilmente que el nombre del formato para una página de vista de quiz es mod-quiz-view. Sin embargo, esta régla tiene unas pocas excepciones:

  • El nombre de formato para la página frontal de Moodle es site-index.
  • El nombre de formato para los cursos en realidad no es simplemente course-view; es course-view-weeks', course-view-topics, etc.
  • Incluso aunque no exite tal página, el nombre de formato all puede ser usado como una opción para cubrir todas las posibiliades. Podemos incluir tantos nombres de formatos como queramos en nuestra definición de formatos aplicables. Cada formato puede ser permitido o no, y hay tres reglas más que ayudan a resolver la pregunta "¿Esta este bloque permitido en esta página, o no?":
  • Los prefijos de un nombre de formato corresponderá al nombre del formato; por ejemplo, mod corresponderá a todos los módulos de actividades. course-view corresponderá a cualquier curso, sin importar el formato del curso. Y finalmente, site también corresponderá a la página frontal (recuerda que el nombre de formato completo es site-index).
  • Entre más especializado sea un nombre que se corresponde con nuestro página, más alta precedencia tiene cuando se decide si el bloque será permitido. Por ejemplo, mod, mod-quiz y mod-quiz-view corresponden todas a la página de vista de quiz. Pero si todas están presentes, mod-quiz-view tendrá precedencia sobre las otras dos porque tiene una mejor correspondencia.
  • El carácter * puede ser usado en lugar de cualquier palabra. Por ejemplo, mod y mod-* son equivalentes. En el momento que esto documento fue escrito, no hay ninguna razón para utilizar este "comodín de correspondencia" pero existe para un uso futuro.
  • El orden en que aparezcan los nombres de formato no hace ninguna diferencia.

Todo lo anterior son suficientes para hacer parecer que la situación suene compleja, así que vamos a ver algunos ejemplos específicos. Primero que todo, para que nuestro bloque aprezca solo en la página frontal de nuestro bloque, usaríamos:

function applicable_formats() {
    return array('site' => true);
}

Dado que all no está, el bloque no se le permite aparecer en ningún formato de curso, pero entonces site se define como true (N. del T verdadero), así que se le permite aparecer en la página frontal (recuerda que site corresponde a site-index porque es un prefijo).

Por ejemplo, si queremos permitir que el bloque aparezca en todos los formatos de curso excepto social, y además que no se permita sino en los cursos, usaríamos:

function applicable_formats() {
    return array('course-view' => true, 'course-view-social' => false);
}

Esta vez, primero permitimos que nuestro bloque aparezca en todos los cursos y luego no lo permitimos explicitamente en el formato social.

Para nuestro ejemplo final, más complicado, supongamos que un bloque puede ser mostrado en la página frontal, en los cursos (pero no en los cursos sociales) y también cuando estamos viendo cualquier módulo de actividad, excepto quiz. Esto sería:

function applicable_formats() {
    return array('site-index' => true,
                 'course-view' => true, 'course-view-social' => false,
                 'mod' => true, 'mod-quiz' => false);
}

No es difícil darse cuenta de que lo anterior logra el objetivo si recordamos que hay una política de "la mejor correspondencia" para determinar el resultado final.

ACTUALIZANDO: Anterior a la versión 1.5, los bloques solo se permitían en los cursos (y en Moodle 1.4, en la página frontal). También, las palabras claves usadas para describir los formatos de curso válidos en ese tiempo fueron cambiados ligeramente y tienen que ser cambiados para permitir una arquitectura más abierta. Vaya al [#appendix_b Apéndice B] para más información sobre los cambios que los bloques viejos tienen que hacer para conformar el nuevo estándar.

Listas e íconos

En esta parte final de la guía, discutiremos someramente una habilidad adicional del sistema de bloques de Moodle, a saber la capacidad de crear muy fácilmente bloques que le muestren una lista de opciones al usuario. Esta lista es mostrada con un ítmem por línea, y una imagen adicional (ícono) próxima al ítem. Un ejemplo de tal bloque de lista es el bloque estándar de Moodle "admin", el cual ilustra todos los puntos discutidos en esta sección.

Como hemos visto, los bloques usan de dos propiedades $this->content]: "text" y "footer". El texto es mostrado tal cual en el contenido del bloque, y el pie de página (N. del T. footer) va abajo en un tamaño de fuente más pequeño. Los bloques de lista usan $this->content->footer en exactamente la misma manera, pero ignoran $this->content->text.

En su lugar, Moodle espera que tales bloques definan otras dos propiedades cuando se llama al método get_content. $this->content->items y $this->content->icons. $this->content->items debe ser un arreglo indexado numéricamente que contiene elementos que representan el HTML de cada ítem de la lista que va a ser mostrada. Usualmente estos ítems serán etiquetas anclas de HTML los cuales dan un enlace a alguna página. $this->content->icons debe ser también un arreglo indexado numéricamente con exactamente tantos ítems como tiene $this->content->items. Cada uno de estos ítems debe ser una etiqueta HTML <img> totalmente calificada, con los atributos "src", "height", "width" y "alt". Obviamente, tiene sentido conservar las imágenes pequeñas y de un tamaño uniforme.

Para decirle a Moodle que queremos un bloque de lista en lugar del estándar bloque de texto, necesitamos hacer un pequeño cambio en nuestra declaración de la clase bloque. En lugar de extender la clase block_base nuestro bloque extenderá la clase block_list. Por ejemplo:

	class block_my_menu extends block_list {
    	// El método init() no necesita cambiar para nada
	}

Además de hacer este cambio, por supuesto debemos modificar también al método [#method_get_content get_content] para construir la variable $this->content como se discutió arriba:

function get_content() {
    if ($this->content !== NULL) {
        return $this->content;
    }

    $this->content = new stdClass;
    $this->content->items = array();
    $this->content->icons = array();
    $this->content->footer = 'Pie de página aquí...';

    $this->content->items[] = '<a href="some_file.php">Menu Option 1</a>';
    $this->content->icons[] = '<img src="images/icons/1.gif" width="16" height="16" alt="" />';

    // Agrega más ítems a la lista aquí

    return $this->content;
}

Para resumir, si queremos crear un bloque de lista en vez de un bloque de texto, solo tenemos que cambiar la declaración de la clase bloque y el método get_content. Al agregar el método mandatorio init como se dijo antes ¡nos dará nuestro primer bloque de lista en todos los tiempos!

Apéndice A: Referencia

En este apéndice se discutirá la clase base block_base de la cual se derivan todas las otras clases de bloque, y presenta todos y cada uno de los métodos que pueden ser sobrescritos por los desarrolladores de bloques en detalle. Los métodos que no deben ser sobrescritos están referidos explícitamente como tales. Después de leer este apéndice, tendrás un entendimiento claro de cada método que deberías o podrías sobrescribir para darle funcionalidad a tu bloque.

Los métodos están divididos en tres categorías: aquellos que puedes usar y sobrescribir en tu bloque, los que no puedes sobrescribir pero puedes usar, y aquellos métodos internos que no debes usar ni sobrescribir. En cada categoría, los métodos se presentan en orden alfabético.

Métodos que puedes usar y sobrescribir libremente

applicable_formats

function applicable_formats() {
    // Caso por defecto: el bloque puede ser usado en cursos y
    // en el index del sitio, pero no en las actividades
    return array('all' => true, 'mod' => false);
}

Este método te permite controlar a cuales formatos puede ser agregado tu bloque. Los formatos de página son formulados de la dirección completa que el script que es usado para mostrar la página. Debes retornar un arreglo con claves que sean los nombres de los formatos de página y los valores booleanos (true o false). Tu bloque solo será permitido en aquellos formatos donde el valor es true. Ejemplos de nombres de formatos son: course-view, site-index (este es una excepción, se refiere a la página frontal del sitio de Moodle), course-format-weeks (se refiere a un formato específico de curso), mod-quiz (se refiere al módulo quiz) y all (este será usado para aquellos formatos a los que no te has referido explicitamente).

Todas las reglas de correspondencia son:

  • Los prefijos de un nombre de formato corresponderá al nombre del formato; por ejemplo, mod corresponderá a todos los módulos de actividades. course-view corresponderá a cualquier curso, sin importar el formato del curso. Y finalmente, site también corresponderá a la página frontal (recuerda que el nombre de formato completo es site-index).
  • Entre más especializado sea un nombre que se corresponde con nuestro página, más alta precedencia tiene cuando se decide si el bloque será permitido. Por ejemplo, mod, mod-quiz y mod-quiz-view corresponden todas a la página de vista de quiz. Pero si todas están presentes, mod-quiz-view tendrá precedencia sobre las otras dos porque tiene una mejor correspondencia.
  • El carácter * puede ser usado en lugar de cualquier palabra. Por ejemplo, mod y mod-* son equivalentes. En el momento que esto documento fue escrito, no hay ninguna razón para utilizar este "comodín de correspondencia" pero existe para un uso fúturo.
  • El orden en que aparezcan los nombres de formato no hace ninguna diferencia.

config_print

 function config_print() {
     // Comportamiento por defecto: muestra el archivo config_global.html
     // No necesitas sobrescribirlo si estás satisfecho con lo anterior
     if (!$this->has_config()) {
         return false;
     }
     global $CFG, $THEME;
     print_simple_box_start('center', '', $THEME->cellheading);
     include($CFG->dirroot.'/blocks/'. $this->name() .'/config_global.html');
     print_simple_box_end();
     return true;
 }

Este método te permite escoger como mostrar la pantalla de configuración global para tu bloque. Esta es la pantalla que se le presenta al administrador cuando escoge "Configuración..." para un bloque específico. Sobrescríbelo si necesitas algo mucho más complejo de lo que la implementación por defecto te permite hacer. Sin embargo, mantén estos puntos en mente:

    1. Si guardas tus opciones de configuración en $CFG, probablemente necesitarás usar $CFG global; antes de incluir cualquier pantalla de configuración HTML.
    2. Los elementos HTML <input> que incluyas en la salidas de los métodos automáticamente serán encerrados en un elemento <form> No tienes que preocuparte acerca de cuando y como este formulario es enviado; sin embargo debes proveer una manera de enviarlos (esto es un <input type="submit" />).

Debes retornar un valor booleano que denote el éxito o la falla de las acciones de tu método.

config_save

function config_save($data) {
    // Comportamiento por defecto: guarda todas las variables como propiedades $CFG
    // No necesitas sobrescribirlo si estás satisfecho con lo anterior
    foreach ($data as $name => $value) {
        set_config($name, $value);
    }
    return true;
}

Este método te permite sobrescribir el mecanismo de almacenamiento de los datos de configuración. El argumento recibido es un arreglo asociativo, siendo las claves los nombres de la configuración y los valores los valores de configuración. La implementación por defecto guarda todo como variables de Moodle $CFG.

Nota que $data no contendrá todos los datos POST enviados puesto que Moodle agrega algunos datos escondidos al formulario para poder procesarlos. Sin embargo antes de llamar a este método quita los campos escondidos de los datos recibidos y así cuando se llama este método solo los datos de configuración "real" se mantienen.

Debes retornar un valor booleano que denote el éxito o la falla de las acciones de tu método.

get_content

function get_content() {
    // Debe ser implementado por la clase derivada.
    return NULL;
}

Al ser llamado, este método debería poblar la variable [#variable_content $this->content] de tu bloque. Poblar la variable significa:

YA SEA
definir $this->content->text y $this->content->footer si tu bloque se deriva de block_base. Estos dos deben ser strings, y pueden contener código HTML arbitrario.

O
definir $this->content->items, $this->content->icons y $this->content->footer si tu bloque se deriva de block_list. Los dos primeros deben ser arreglos numéricamente indexados con exactamente el mismo número de elementos. $this->content->items es un arreglo de strings que pueden contener HTML arbitrario mientras $this->content->icons también debe contener strings, pero estos deben ser HTML <img> totalmente calificadas y nada más. $this->content->footer es un string, como en el anterior.

Si pones todas todas estas variables en su valor por defecto "vacío" (arreglos vacíos para los arreglos y strings vacíos para los strings), el bloque no se mostrará en lo absoluto excepto para los usuarios editores. Esta es una buena manera de que tu bloque se esconda a si mismo si no hay razón para mostrarlo.

Antes de comenzar a poblar $this->content, también debes incluir un simple chequeo del cache. Si $this->content es exactamente igual a NULL, entonces proceda normalmente, mientras que si no lo es, retorne el valor existente en lugar de calcularlo una vez más. Si no haces esto, Moodle sufrirá una caída en su desempeño.

En cualquier caso, tu método debe retornar la variable $this->content completamente construida.

has_config

function has_config() {
    return false;
}

Este método debe retornar un valor booleano que denota si tu bloque quiere presentar una interfaz de configuración al administrador del sitio o no. La configuración que esta interfaz ofrece impactará a todas las instancias del bloque igualmente.

Para realmente implementar la interfaz de configuración, necesitarás ya sea confiar en método config_print por defecto, o sobrescribirlo. La guía completa contiene más información al respecto.

hide_header

function hide_header() {
    //Por defecto, false--> se muestra la cabecera
    return false;
}

Este método debe retornar un valor booleano que denota si nuestro bloque quiere esconder su cabecera (o título). Así, si lo sobrescribes para que retorne true (N. del T verdadero), tu bloque no mostrará un título a menos que el usuario actual esté en modo de edición.

html_attributes

function html_attributes() {
    // Caso por defecto: un id con la instancia y una clase con nuestro nombre en ella
    return array('id' => 'inst'.$this->instance->id, 'class' => 'block_'. $this->name());
}

Este método debe retornar un arreglo asociativo de atributos HTML que le serán entregados al elemento contenedor de tu bloque cuando Moodle construya la salida HTML. No se realizara ninguna limpieza en el código.

Si quieres sobrescribir este método, debes retornar los atributos por defecto tanto como los que tu agregaste. La forma recomendada de hacer esto es:

function html_attributes() {
    $attrs = parent::html_attributes();
    // Agrega tus propios atributos aquí, por ejemplo:
    // $attrs['width'] = '50%';
    return $attrs;
}

init

function init() {
    $this->title = get_string('simplehtml', 'block_simplehtml');
    $this->version = 2004111200;
}

Este método debe ser implementado para todos los bloques. Tiene que asignarles valores significativos a las variables objeto $this->title, y $this->version (la cual es usada por Moodle para realizar actualizaciones automáticas cuando esten disponibles).

No se espera un valor de retorno de este método.

instance_allow_config

function instance_allow_config() {
    return false;
}

Este método debe retornar un valor booleano. True indica que tu bloque quiere tener una configuración por instancia, mientras false significa que no. Si quieres implementar la configuración de instancia, necesitarás algunos pasos adicionales aparte de sobrescribir este método; refiérete a la guía completa para más información.

El valor retornado por este método es irrelevante si instance_allow_multiple retorna verdadero; se asume que si quieres múltiples instancias entonces cada una necesita su propia configuración.

instance_allow_multiple

function instance_allow_multiple() {
    // ¿Vas a permitir múltiples instancias de cada bloque?
    // Si sí, entonces se asume que el bloque USARÁ configuración por instancia
    return false;
}

Este método debe retornar un valor booleano, indicando si quieres permitir múltiples instancias de este bloque en una misma página o no. Si permites múltiples instancias, se asume que darás configuración por instancia para el bloque. Así que necesitarás algunos pasos adicionales aparte de sobrescribir este método; refiérete a la guía completa para más información.

instance_config_print

 function instance_config_print() {
     // Comportamiento por defecto: muestra el archivo config_instance.html
     // No necesitas sobrescribirlo si estás satisfecho con lo anterior
 
     if (!$this->instance_allow_multiple() && !$this->instance_allow_config()) {
         return false;
     }
     global $CFG, $THEME;
 
     if (is_file($CFG->dirroot .'/blocks/'. $this->name() .'/config_instance.html')) {
         print_simple_box_start('center', '', $THEME->cellheading);
         include($CFG->dirroot .'/blocks/'. $this->name() .'/config_instance.html');
         print_simple_box_end();
     } else {
         notice(get_string('blockconfigbad'),
                str_replace('blockaction=', 'dummy=', qualified_me()));
     }
     
     return true;
 }

Este método te permite seleccionar como mostrar la pantalla de configuración de instancia para tu bloque. Sobrescribelo si necesitas algo mucho más complejo de lo que la configuración por defecto te permite hacer. Ten en mente que cualquier cosa que pongas de salida de config_print, será encapsulada en un formulario HTML automáticamente. Solo necesitas tener una forma de enviar el formulario.

Debes retornar un valor booleano que denote el éxito o la falla de las acciones de tu método.

instance_config_save

function instance_config_save($data) {
    $data = stripslashes_recursive($data);
    $this->config = $data;
    return set_field('block_instance', 'configdata', base64_encode(serialize($data)), 
                     'id', $this->instance->id);
}

Este método te permite sobrescribir el método de almacenamiento para los datos de configuración de tu instancia. El argumento recibido es un arreglo asociativo, siendo las claves los nombres de configuración y los valores los valores de configuración.

La configuración debe ser almacenada en el campo "configdata" del registro en la base de datos tal que Moodle pueda autocargarlos cuando tu bloque es construido. Sin embargo aún puedes querer sobrescribir este método si necesitas hacer algo aparte de guardar datos. En ese caso, debes hacer el procesamiento de datos que quieras y luego llamar a parent::instance_config_save($data) con tu nuevo arreglo $data. Esto evitará que nuestro bloque se rompa si la implementación por defecto de instance_config_save cambia en el futuro.

Nota que $data no contendrá todos los datos POST enviados puesto que Moodle agrega algunos datos escondidos al formulario para poder procesarlos. Sin embargo, antes de llamar a este método quita los campos escondidos de los datos recibidos y así cuando se llama este método solo los datos de configuración "real" se mantienen.

Si quieres actualizar la copia guardada de los datos de configuración mientras corre (por ejemplo para mantener algunos cambios que hiciste programáticamente), no debes usar este método. El procedimiento correcto para tal propósito es llamar a instance_config_commit.

Debes retornar un valor booleano que denote el éxito o la falla de las acciones de tu método.

preferred_width

function preferred_width() {
    // Caso por defecto: el bloque quiere un ancho de 180 pixeles
    return 180;
}

Este método debe retornar un valor entero, el cuál es el número de píxeles de ancho que tu bloque quiere tomar cuando sea mostrado. Moodle tratará de respetar tu petición, pero esto realmente depende de la implementación del formato de página en la que tu bloque está siendo mostrado asi que no hay garantías. Realmente puedes tener exactamente lo quieres o cualquier otro ancho que el formato decida darte, aunque obviamente se hará un esfuerzo por acomodar tu bloque.

En este punto la principal lógica de despliegue, es posicionar el máximo ancho pedido por los bloques que van a ser mostrados, limitándolos tanto por encima como por debajo para evitar que un bloque con mal comportamiento dañe el formato.

refresh_content

function refresh_content() {
    // Nada especial aquí, depende de content()
    $this->content = NULL;
    return $this->get_content();
}

Este método debe hacer que tu bloque recalcule su contenido inmediatamente. Si sigues los lineamientos para get_content, los cuales dicen que hay que respetar valor actual del contenido a menos que este sea NULL, entonces la implementación por defecto hará su trabajo bastante bien. Debes retornar el nuevo valor de $this->content después de refrescarlo.

specialization

function specialization() {
    // Solo para asegurarse de que este método existe.
}

Este método es llamado automáticamente por el framework inmediatamente después de que tus datos de instancia (los cuáles incluyen el tipo de página, el id y todos los datos de configuración de la instancia) son cargados de la base de datos. Si hay algo que necesites hacer tan pronto como estos datos estén disponibles y que no puede ser hecho antes, debes sobrescribir este método.

Los datos de instancia estarán disponibles en las variables $this->instance y $this->config.

Este método no debe retornar nada en absoluto.

Métodos que no debes sobrescribir pero puedes querer usar:

instance_config_commit

function instance_config_commit() {
    return set_field('block_instance',
                     'configdata', base64_encode(serialize($this->config)),
                     'id', $this->instance->id);
}

Este método guarda el contenido acutal de $this->config en la base de datos. si necesitas hacer un cambio en la confuguración de una instancia de bloque mientras está corriendo (y no a través del camino usual de dejar al usuario cambiarlo), solo haz los cambios que quieres en $this->config y luego llama este método.

get_content_type

function get_content_type() {
    return $this->content_type;
}

Este método retorna el valor de $this->content_type, y es la manera preferida de acceder a esta variable. Se garantiza que siempre funcionará, ahora y siempre. No se recomienda acceder directamente a la variable; cambios futuros en las librerias podrían romper la compatibilidad con el código que hace esto.

get_title

function get_title() {
    return $this->title;
}

Este método retorna el valor de $this->title, y es la manera preferida de acceder a esta variable. Se garantiza que siempre funcionará, ahora y siempre. No se recomienda acceder directamente a la variable; cambios futuros en las librerias podrían romper la compatibilidad con el código que hace esto.

get_version

function get_version() {
    return $this->version;
}

Este método retorna el valor de $this->version, y es la manera preferida de acceder a esta variable. Se garantiza que siempre funcionará, ahora y siempre. No se recomienda acceder directamente a la variable; cambios futuros en las librerias podrían romper la compatibilidad con el código que hace esto.

is_empty

Para bloques que extienden la clase block_base:

	function is_empty() {
   	$this->get_content();
    return(empty($this->content->text) && empty($this->content->footer));
}

Para bloques que extienden la clase block_list:

function is_empty() {
    $this->get_content();
    return (empty($this->content->items) && empty($this->content->footer));
}

Este método retorna un valor booleano verdadero/falso, dependiendo de si el bloque tiene cualquier contenido para mostrar. Los bloques sin contenido no son mostrados por el framework.

name

function name() {
    static $myname;
    if ($myname === NULL) {
        $myname = strtolower(get_class($this));
        $myname = substr($myname, strpos($myname, '_') + 1);
    }
    return $myname;
}

Este método retorna el nombre interno de tu bloque dentro de Moodle, sin el prefijo block_. Obtener el nombre del objeto bloque es útil algunas veces porque puede ser usado para escribir código que no conoce el nombre del bloque (y así es más genérico y reusable). Para un ejemplo de esta técnica, vea el método config_print.

Métodos que no debes sobrescribir ni usar para nada:

_self_test

Este es un método privado, no se da descripción.

_add_edit_controls

Este es un método privado, no se da descripción.

_load_instance

Este es un método privado, no se da descripción.

_print_block

Este es un método privado, no se da descripción.

_print_shadow

Este es un método privado, no se da descripción.

La clase block_base también tiene unas pocas variables miembros estándar que son manipuladas por sus métodos. Estas variables, el propósito de cada una y el tipo de datos que se espera guarde son explicadas en la próxima sección de este apéndice.

Variables de clase:

$this->config

Esta variable guarda todos los datos especializados de configuración de instancia que han sido dadas para esta instancia de bloque específica (objeto). Es un objeto de tipo stdClass, con variables miembros que corrresponden directamente con los elementos HTML <input> en el archivo de bloque config_instance.html.

La variable es inicializada justo después de que se construye el objeto bloque, inmediatamente antes de que [#method_specialization specialization] sea llamado por el objeto. Es posible que el bloque no tenga configuración de instancia, en cuyo caso la variable será NULL.

Es obvio que hay una relación directa entre esta variable y el campo configdata en la tabla mdl_block_instance. Sin embargo, se recomienda fuertemente que te refrenes de acceder por ti mísmo el campo configdata. Si es absolutamente necesario que actualices su valor en cualquier momento, se recomienda que llames al método instance_config_commit para hacer el trabajo real.

$this->content_type

Esta variable le dice a Moodle sobre que tipo de contenido debe asumir que tenga el bloque y es usada para diferenciar los bloques de texto de los bloques de lista. Es esencial que tenga un valor significativo, ya que Moodle depende de esto para mostrar el bloque correctamente en la pantalla. Consecuentemente, esta variable está cercanamente relacionada con la variable $this->content. Se espera que la variable tenga un valor válido después de el framework llama el método init para cada bloque.

Los únicos valores válidos para esta variable son las dos constantes llamadas BLOCK_TYPE_TEXT y BLOCK_TYPE_LIST.

$this->content

Esta variable guarda el contenido real que se muestra dentro de cada bloque. Los valores válidos son o NULL, o un objeto de clase stdClass, el cual debe tener variables miembros específicos como se explica más abajo. Normalmente, comienza su vida con un valor de NULL y queda completamente construido (esto es, un objeto) cuando se llama get_content.

Después de que están completamente contruido, se espera que este objeto tenga ciertas propiedades, dependiendo del valor de $this->content_type. Específicamente:

  • Si $this->content_type es BLOCK_TYPE_TEXT, entonces se espera que $this->content tenga los siguientes miembros variables:
    • text
      Este es un string de longitud y contenido arbitrario. Se muestra dentro del área del bloque, y puede contener HTML.
    • footer
      Este es un string de longitud y contenido arbitrario. Se muestra debajo del texto, usando un tamaño de fuente pequeño. También puede contener HTML
  • Si $this->content_type es BLOCK_TYPE_LIST, entonces se espera que $this->content tenga los siguientes miembros variables:
    • items
      Este es un arreglo de strings indexado numéricamente, los cuales guardan un título por cada ítem en la lista que será mostrada en el área del bloque. Dado que usualmente tales listas funcionan como menús, el título para cada ítem normalmente es una etiqueta HTML <a> completamente calificada.
    • icons
      Este es un arreglo de strings indexado numéricamente el cual representa las imágenes mostradas antes de cada ítem de la lista. Se sigue de aquí que debe tener exactamente el mismo número de elementos que el miembro variable items. Cada item en este arreglo debe ser una etiqueta HTML <img> completamente calificada.
    • footer
      Este es un string de longitud y contenido arbitrario. Se muestra debajo del texto, usando un tamaño de fuente pequeño. También puede contener HTML.

$this->instance

Este miembro variable guarda toda la información específica que diferencia una instancia de bloque (esto es, el objeto PHP que lo incorpora) de otra. Es un objeto del tipo stdClass recuperado al llamar get_record en la tabla mdl_block_instance. Sus miembros variables, entonces, se corresponden directamente con los campos en esa tabla. Se inicializa inmediatamente después de que el mismo objeto bloque es contruido.

$this->title

Esta variable es un string que contiene el nombre entendible por los humanos del bloque. Es usado para referirse a bloques de ese tipo a través de Moodle, por ejemplo en la pantanlla del administrador de configuración del bloque y en el menú de añadir bloques en la edición del profesor. También es el título que se pone cuando el bloque es mostrado en la pantalla, aunque los bloques pueden específcamente cambiar su título por algo más si lo desean (ver abajo). Se espera que la variable tenga un valor válido después de que el framework llama el método init para cada objeto.

En el caso de los bloques que pueden querer configurar sus títulos dinámicamente a través de la configuración de instancia, es áun esencial dar un título válido dentro de init. Este puede ser sobrescrito cuando el método specialization es llamado por el framework:

function specialization() {
    // En este punto, $this->instance y $this->config están disponibles
    // para su uso. Ahora podemos cambiar lo que sea que queramos.
    $this->title = $this->config->variable_holding_the_title;
}

$this->version

Esta variable debe guardar el número de la versión del bloque en la forma YYYYMMDDXX, por convención a través de Moodle. El número de versión es usado por Moodle para detectar cuando ha sido mejorado un bloque y consecuentemente se necesita correr el código de actualización del bloque para llevar la versión "vieja" de los datos del bloque al día. Se espera que la variable tenga un valor válido después de que el método init es llamado para cada bloque.

La mayoría de los bloques no guardan datos propios complejos en la base de datos de la manera que lo hacen los módulos, así que en la mayoría de los casos realmente no pasa nada durante la actualización de la versión de un bloque. Sin embargo, el número de la versión se muestra en la interfaz de administración de los bloques. Así que es buena práctica cambiar el número de versión de tu bloque cuando este gana nuevas funcionalidades o se le hacen correcciones de bugs importantes, para permitirles a los adminsitradores de sitios identificar fácilmente la versión exacta del bloque con la cual están trabajando.

Apareciendo a través del código relacionado con la API de bloque, hay un número de constantes predefinidas que son usadas para evitar el uso de "numeros mágicos" en el código. Estas constantes son:

Constantes nombradas:

BLOCK_TYPE_LIST

Este es uno de los dos valores válidos para el miembro variable $this->content_type de cada bloque. Su valor específica los requerimientos exactos que Moodle tendrá para $this->content.

BLOCK_TYPE_TEXT

Este es uno de los dos valores válidos para el miembro variable $this->content_type de cada bloque. Su valor específica los requerimientos exactos que Moodle tendrá para $this->content.

Apéndice B: Diferencias con la API de los bloques para versiones anteriores a Moodle 1.5

Este apéndice discutirá que cambios fueron introducidos en la API de los bloques de Moodle 1.5 y que necesitan hacer los desarrolladores para actualizar sus bloques para que sean completamente compatibles con Moodle 1.5. Desafortunadamente, con estos cambios se ha roto la compatibilidad hacia atrás; esto significa que los bloques de Moodle 1.4 no funcionarán nunca con 1.5 y viceversa.

Cambiaron las convenciones de nombres

En Moodle 1.4, se requería que todas las clases bloque tuvieran un nombre como CourseBlock_algo y la clase base de la cual se derivaban era MoodleBlock. Esto cambio en Moodle 1.5, para poner las convenciones de nombres en línea con otros aspectos orientados a objetos de Moodle (por ejemplo hay clases enrolment_base, resource_base, etc). Las nuevas clases deben entonces llamarse block_algo y derivarse de block_base. Esto significa que con el objeto de hacer un bloque compatible con Moodle 1.5, necesitas cambiar la definicion de clase de

class CourseBlock_online_users extends MoodleBlock { ... }

a

class block_online_users extends block_base { ... }

Una exepción a lo anterior es el caso especial donde se quiere que el bloque muestre una lista de ítems en lugar de texto arbitrario; en ese caso la clase bloque debe derviarse de la clase block_list, así:

class block_admin extends block_list { ... }

Constructor versus init()

En Moodle 1.4, en cada clase de bloque era mandatorio definir un constructor el cual aceptaba un registro de datos como argumento (el ejemplo es del bloque real de Usuarios online):

    function CourseBlock_online_users ($course) {
        $this->title = get_string('blockname','block_online_users');
        $this->content_type = BLOCK_TYPE_TEXT;
        $this->course = $course;
        $this->version = 2004052700;
    }

En contraste, Moodle 1.5 se olvida del constructor y te pide que definas un método init() que no recibe argumentos:

    function init() {
        $this->title = get_string('blockname','block_online_users');
        $this->version = 2004111600;
    }

Por supuesto, esto te deja sin acceso al objeto $course, el cual puedes necesitar realmente. Puesto que probablemente se necesitará dentro de get_content, la manera de recuperarlo es usando este código:

    $course = get_record('course', 'id', $this->instance->pageid);

Si vas a necesitar acceso a $course desde otros métodos aparte de get_content, puedes traer el objeto $course dentro del método specialization y guardarlo como una variable de clase para su uso posterior, con el fin de evitar realizar la misma consulta varias veces:

    function specialization() {
        $this->course = get_record('course', 'id', $this->instance->pageid);
    }

Bloques con configuración

En Moodle 1.4, los bloques solo podían tener lo que ahora (en Moodle 1.5) se llama opciones de "configuración global", para diferenciarlo de las nuevas opciones de "configuración de instancia". Si tu bloque tiene soporte para configuración, necesitas hacer esto:

  1. Renombra tu archivo config.html como config_global.html.
  2. Edita el archivo recientemente renombrado y quita completamente la etiqueta <form> (Moodle ahora envuelve tu configuración en un formulario automáticamente).
  3. Si estas usando cualquier etiqueta HTML <input> diferentes a aquellas que afectan directamente tu configuración (por ejemplo, "sesskey"), QUITALAS también (Moodle las agregará automáticamente si se necesitan)./li>
  4. Si has sobrescrito print_config, renombra tu método como config_print.
  5. Si has sobrescrito handle_config, renombra tu método como config_save.

Bloques con formatos aplicables personalizados

La forma correcta de especificar los formatos en que quieres permitir o no que exista tu bloque ha sido re-hecha para Moodle1.5 para tomar en cuenta que los los bloques ya no estan restringidos solo a los cursos. Para que los bloques mantengan el comportamiento esperado, debes cambiar estos nombres de formato (claves de arreglos en el valor que retorna applicable_formats) si son usados en tu bloque:

  • social debe convertirse en course-view-social
  • topics debe convertirse en course-view-topics
  • weeks debe convertirse en course-view-weeks

También debes tener en cuenta que ahora está la posibilidad de que los bloques se muestren también en otras páginas, como la página introductoria que los usuarios ven cuando entran en un módulo de actividad. Puedes entonces necesitar hacer la especificación para los formatos aplicables más restrictiva para mantener a tu bloque fuera de las páginas donde no se supone que esté. También hay cambios sutiles en la manera en que la decisión final de permitir o no un bloque se hace. Para detalles técnicos refiérete a la definición de applicable_formats, y para un ejemplo más extenso lee la sección dedicada a este asunto.

Esto es todo; ¡ahora tu bloque estará listo para usarse en Moodle 1.5!