Cajón de sastre

Este el lugar de la cocina donde se guardan las recetas que no tienen espacio en ninguno de los otros cajones o armarios. Podríamos llamarle "Cajón de cocinero" o "Cajón de Drupal", pero bueno, quien sabe si en breve además de recetas publicamos patrones...quien sabe :)

Accesibilidad. Problemas de validación en la vista "/event" del módulo event

End tag for "ul" omitted, but OMITTAG NO was specified.
El anterior error aparece al validar la accesibilidad a la vista 'event' en modo lista. Ésta vista es creada por el módulo event por lo que para solucionarlo primero tenemos que observar como la ha creado. De ésto se encarga el fichero event.module, y como era de esperar ésta tiene su tema: event_node_list. La función del tema: function theme_event_node_list ($node){ se especifica en el fichero event.theme.
La solución es copiar dicha función e integrarla en el template.php (fichero que se encuentra dentro de su tema). Los cambios a realizar son los siguientes:

  • Introducir ésta función en template.php. Basta con pegar la función y cambiar el nombre. Poner: function phptemplate_event_node_list($node, $module=NULL) (Cambiar theme por phptemplate).
  • Arreglar el error. Éste aparece cuando se intenta introducir el teaser del cuerpo, en la línea de código:

    <?php

    $output
    .= '<div class="content">'. check_markup($node->teaser) .'</div></div>'."\n";
    ?>


    Basta con eliminar la llamada a check_markup. Dejarlo así:
    <?php
    $output
    .= '<div class="content">'.'</div></div>'."\n";
    ?>

Accesibilidad. Problemas de validación. Id = edit-submit , edit-mail ...

ID "edit-submit" already defined.

En las páginas o formularios (por ejemplo en la del buscador, las vistas con filtros expuestos, el formulario de contacto, el formulario de añadir comentarios...) dónde están los mismos botones o campos (botón 'submit', campo 'mail'..), es muy común encontrarse con el anterior error de validación.

Éste error significa que el id al ser un identificador único debería tener un valor diferente por cada botón.. por ello lo único que hay que hacer es darle un id distinto a cada caso. Éste cambio se puede realizar con un form_alter de drupal. Para más ayuda ver el artículo El hook form_alter.

A continuación mostramos un ejemplo de cómo eliminar el fallo de accesibilidad para las páginas dónde aparece el formulario de añadir comentarios. En este caso salen dos errores uno por el botón submit y otro por el campo mail. Para solucionarlo basta hacer lo siguiente, cambiar el id para esos casos:

<?php

function mimodulo_form_alter($form_id, &$form){
 
// Validation para el formulario de los comentarios
 
if ($form_id == 'comment_form') {
   
$form['mail']['#id'] = 'edit-mail-comment';
   
$form['submit']['#id'] = 'edit-submit-comment';
  }
}
?>

Bug del módulo Panels 5.x-2.0-beta1

Módulo: panels 5.x-2.0-beta1

Si con el módulo Panels 5.x-2.0-beta1 os sale el siguiente error:
warning: Invalid argument supplied for foreach() in /var/www/drupal/sites/all/modules/panels/includes/plugins.inc on line 423.

Debeis añadir la línea de código: "$types = array()" al archivo panels_views.module en la línea 692:

<?php
function panels_views_content_types() {
 
$panes = panels_views_load_all();
+
$types = array();
  foreach (
$panes as $name => $pv) {
?>

Basado en el artículo: warning in plugins.inc

Cómo configurar captcha en la acción node/add

Caso práctico! Hemos instalado el modulo captcha en nuestro drupal, lo tenemos configurado de tal manera que cuando alguien hace un comentario en un post haya que teclear los códigos generados por captcha.
En nuestro site tenemos un tipo de contenido que lo pueden generar usuarios anónimos y nos hemos encontrado con el problema de que el módulo captcha en la configuración por defecto sólo aparece cuando añades comentarios (lo he configurado así en las opciones generales) pero nosotros queremos que salga también en la acción node/add/tipodecontenido

Solución:

Seleccionamos esta opción en la configuración general:

Y ahora nos vamos a el tipo de contenido que queramos añadirle captcha
Por ejemplo si el tipo de contenido seria pagina haríamos lo siguiente: (logueados como admin) vamos a admin , crear contenido , pagina o http://tu_site/node/add/pagina
y veremos lo siguiente:

La opción del recuadro azul es la que tenemos que seleccionar, con esto, el modulo captcha ya saldrá siempre cuando los usuarios anónimos publiquen contenido del tipo pagina.
-

Conectarse a varias bases de datos y crear tablas temporales

1. Conectarse a otra base de datos
Para acceder a múltiples bases de datos, basta con indicar en el fichero settings.php las bases de datos deseadas y luego en el correspondiente módulo, fichero.. y por último realizar correctamente las conexiones y desconexiones.

1. Indicar las bases de datos en settings.php. Habrá que sustituir la siguiente línea de código:
$db_url = 'mysql://user:contraseña@localhost/nombre_base_datos';
?>
por otras donde se indicaran cúales son: Por ejemplo la de por defecto y la secundaria.
$db_url['default'] = 'mysql://user:contraseña@localhost/nombre_base_datos_1';
$db_url['secondary'] = 'mysql://user:contraseña@localhost/nombre_base_datos_2';
?>

2. Realizar las conexiones. Para acceder a la base de datos por defecto no abrá que realizar ningún cambio, únicamente cúando se desee conectar al resto.
Por ejemplo cuando deseemos pintar una consulta de la tabla 'secondary' abrá que añadir el siguiente código:
db_set_active('secondary'); //conectarse a la base de datos
$consulta=db_fetch_object(db_query("SELECT * FROM {tabla} WHERE ..")); //realizar la consulta de la tabla que está en la base de datos secondary
print_r ('pintar el resultado...'.$consulta); //pintar la consulta o lo que se desee realizar con ella..
db_set_active ('default'); //volver a conectarse a la base de datos por defecto.
?>

2. Crear tablas temporales
Para crear tablas temporales es necesario usar la function db_query_temporary de drupal.

Los dos parametros de ésta fución son los siguientes:
db_query_temporary($query, $table)

  • $query: Es un array que contiene una consulta a alguna tabla. El resultado de ésta consulta será lo que se añada a la tabla temporal.
  • $table: Nombre de la tabla temporal que se desea crear

Un ejemplo podría ser el siguiente:
$query= "SELECT * FROM {node} WHERE nid>40"; //Una consulta..
$tabla_temporal=db_query_temporary($query, 'nombre_tabla_temporal'); //introduzco el resultado de la anterior consulta en una tabla temporal: 'nombre_tabla_temporal'
?>
La tabla ya está creada y completa, el acceso a ella es tan simple como a cualquier otra.

El hook Form_alter

Si se quieren hacer modificaciones, como añadir, borrar o alterar campos en formularios (como pueden ser los de añadir contenido, buscadores, logarse..) basta con un utilizar el hook form_alter de drupal.

Los dos parametros de éste hook son los siguientes:
hook_form_alter($form_id, &$form)

  • $form_id: Representa la identidad del formulario, es el nombre de la función que genera el formulario.
  • $form: Array que contiene las características de todos los elementos del formulario

Para una mejor compresión a continuación mostramos una receta que contiene cómo ingrediente principal el hook form_alter.

Al añadir un nuevo contenido en drupal (existentes como una página u otros contenidos creados con el módulo cck de drupal se puede observar que por el final del formulario siempre aparece un campo de título 'Mensaje de registro'. En muchos casos éste nunca es rellenado por lo que en ésta receta enseñaremos a eliminarlo.

formlario ejemplo

Para ello lo primero que hay que hacer es crear el módulo dónde se escribirá la siguiente función:

function_nombre_módulo_form_alter($form_id, &$form){

Cuando no se saben como se llama exactamente el formulario o los campos que contiene éste, lo mejor es hacer unos 'print' de los parametros anteriormente mencionados, y de ésta forma seran pintados en la página del formulario de drupal:

<?php

function_nombre_módulo_form_alter
($form_id, &$form){
   
print_r ($form_id) ;  //identifica el formulario
   
print_r ($form); //muestra todos los datos de todos los campos del formulario

   
}
?>

Parte del resultado (recordando que la parte que nos interesa es el campo de mensaje de registro del tipo de contenido 'receta'..) es el siguiente.
$form_id:

receta_node_form

Gracias al $form_id vemos que el formulario se llama “receta_node_form”, por lo que si los cambios que queremos realizar únicamente queremos que ocurran para éste formulario bastaría con introducir un if dentro del hook:

<?php
function_nombre_módulo_form_alter
($form_id, &$form){
    if (
$form_id=='receta_node_form'){
       
//los cambios a realizar..
   
}
    }
?>

$form:

[log] => Array
        (
            [#type] => textarea
            [#title] => Mensaje de registro
            [#rows] => 2
            [#weight] => 20
            [#description] => Una explicación de las adiciones o actualizaciones que se han hecho para ayudar a que otros autores entiendan sus motivaciones.
        )
    [author] => Array
        (
            [#type] => fieldset
            [#access] => 1
            [#title] => Información de autoría
            [#collapsible] => 1
            [#collapsed] => 1
            [#weight] => 20

Entre todo el array que muestra este parámetro nos quedamos con el nombre del campo que nos interesa eliminar : 'log'. Y finalmente mediante la funcion 'unset' (encargada de borrar variables) borramos ese campo:

<?php
function_nombre_módulo_form_alter
($form_id, &$form){
      if (
$form_id=='receta_node_form'){
        unset (
$form['log']);
      }
    }
?>

Adjuntamos el pequeño módulo (llamado 'form_alter') explicado en esta receta.

En ésta receta se ha visto eliminar un campo, pero tambíen se pueden modificar o añadir. Por ejemplo:

  • Modificar la descripción del campo de registro:
    <?php
       $form
    ['log']['#description'] = 'nueva descripcion del campo..';
    ?>
  • Crear un nuevo formulario, por ejemplo un select de nombre ¿Sabes utilizar un form_alter? y con respuestas si o no.
    <?php
    $defecto
    =1;
    $options = array('si','no');
      
    $form['utilizar'] = array(
         
    '#type' => 'select',
         
    '#title'=> 'Sabes utilizar el form_alter',
         
    '#default_value' => $defecto,
         
    '#options' => $options,
         
    '#description' => t('Escoja entre las opciones si y no')
    );
    ?>

Multisites con Drupal

Saludos a tod@s desde la trastienda del esta nuestra cocina colaborativa.

De tod@s es sabido que para que l@s grandes chefs trabajen a gusto y lleguen al climax de creatividad y buen gusto hace falta crear y mantener un entorno amigable, con todos los elementos disponibles sin demasiado esfuerzo (...que los cuchillos estén afilados, las cazuelas limpias y en su sitio, y todos los elementos a mano. Es nuestra labor, amig@s de la trastienda: somos pinches de cocina, y a mucha honra, que sin nosotr@ no son nada y viceversa) y dejar los quebraderos de cabeza para lo que realmente interesa: un gran plato rico,rico y con fundamento.

Hoy voy a explicar cómo mantener todos los cacharros ordenados en un único cajón, o lo que es lo mismo: cómo tener todos nuestros sitios con Drupal en un único lugar, con un único núcleo, el llamado Drupal Multisites.

La idea es que sólo exista un único núcleo y todos los sites cuelguen de un directorio de el mismo. Las ventajas son evidentes, pero, desde nuestra perspectiva de pinches, podemos destacar:
-Actualización de un drupal (aunque tengamos 1000 sitios con drupal)
-Automatización de creación de nuevos Drupales
-Automatización de copias de seguridad

Para información más detallada de cómo instalar drupal:
http://www.cocinandocondrupal.net/node/43

Descargar drupal
Primero nos situamos en el directorio donde vayamos a instalar (generalmente /var/www si lo instalamos en nuestra máquina y descargamos la última versión de drupal mediante wget:

$ wget http://ftp.drupal.org/files/projects/drupal-5.X.tar.gz

Ponerlo en su sitio
Descomprimimos:

$ tar -zxvf drupal-5.X.tar.gz

y renombramos:

$ mv drupal-5.X drupal_base

Cambiar permisos
Cambiamos propietario y grupo:

chown -R root:www-data drupal_base
chmod 464 drupal_base/sites/default/settings.php

Base de datos
Hecho esto solo nos falta crear la base de datos el usuario de la base de datos:

$ mysqladmin -u root -p create drupal_base
$ mysql -u root -p drupal_base

(desde aquí hasta exit; estamos en la consola mysql)


GRANT ALL PRIVILEGES ON drupal_base.* TO drupal_base@localhost IDENTIFIED BY 'password_drupal_base';
Flush privileges;
exit;

Montar el Multisites
Crear el directorio para alojar los ficheros del sitio por defecto

[/var/www]# cd drupal_base
[/var/www/drupal_base]# mkdir files
[/var/www/drupal_base]# chmod 777 files

Crear los directorios para alojar los ficheros, modulos y temas de cada sitio

[/var/www/drupal_base]# cd sites/all
[/var/www/drupal_base/sites/all]# mkdir modules
[/var/www/drupal_base/sites/all]# mkdir themes
[/var/www/drupal_base/sites/all]# cd modules
[/var/www/drupal_base/sites/all/modules]# mkdir custom
[/var/www/drupal_base/sites/all/modules]# mkdir contrib
[/var/www/drupal_base/sites/all/modules]# cd ../
[/var/www/drupal_base/sites/all]# cd themes
[/var/www/drupal_base/sites/all/themes]# mkdir custom
[/var/www/drupal_base/sites/all/themes]# mkdir contrib

Creamos el directorio de prueba "www.nuevodominio.es":

[/var/www/drupal_base/sites/all/themes]# cd ../
[/var/www/drupal_base/sites/all]# cd ../
[/var/www/drupal_base/sites]# mkdir www.nuevodominio.es

y sus 3 subdirectorios files, modules y themes.

[/var/www/drupal_base/sites]# cd www.nuevodominio.es
[/var/www/drupal_base/sites/www.nuevodominio.es]# mkdir files

cambiamos los permisos de "settings.php" del default y lo copiamos a www.nuevodominio.es:

[/var/www/drupal_base/sites]# cd default
[/var/www/drupal_base/sites/default]# chmod 777 settings.php
[/var/www/drupal_base/sites/default]# cd ../
[/var/www/drupal_base/sites]# cp -rp sites/default sites/www.nuevodominio.es

Hay que volver a dejarlo como 444

[/var/www/drupal_base/sites/default]# chmod 444 settings.php

Creamos la base de datos para el nuevo sitio

$ mysqladmin -u root -p create drupal_wwwnuevodominioes

$ mysql -u root -p drupal_wwwnuevodominioes

(desde aquí hasta exit; estamos en la consola mysql)

mysql> GRANT ALL PRIVILEGES ON drupal_wwwnuevodominioes.* TO 'wwwnuevodominioes_miusuario'@'localhost' IDENTIFIED BY 'mipassword';
mysql> Flush privileges;
mysql> exit

Vamos al navegador y apuntamos al sitio creado.
Introducimos los datos correspondientes y volvemos a consola a poner permisos de sólo lectura al settings.php

[/var/www/drupal_base/sites]# cd www.nuevodominio.es
[/var/www/drupal_base/sites/www.nuevodominio.es]# chmod 444 settings.php

Descargar módulos que vamos a usar
Los descargamos a /var/www/drupal_base/sites/all/modules/contrib
(esto del contrib y custom nos va a permitir diferenciar los que son desarrollados por unos o por otros)

$ wget http://...

A partir de aquí es opcional, depende de la configuración propia de cada servidor.

Servidor de nombres
Crear entrada dominio recién creado.
Aquí podremos encontrar dos posibilidades:

1ª Que queramos un subdominio dun dominio existente, para lo cual la mejor solución es utilizar un wildcard en el fichero de Bind del dominio, del tipo:

@ IN A 192.168.1.50
localhost A 127.0.0.1
nuevodominio.es. A 192.168.1.50
*.nuevodominio.es. CNAME nuevodominio.es.

todas las peticiones a nuevodominio.es irán al mismo sitio, y podremos ir creando subdominios grestionados por el propio Drupal

2º Que queramos crear un dominio nuevo, para lo cual deberemos crear el nuevo fichero y reiniciar Bind

Apache

Caso 1º
Si estamos creando un subdominio de un dominio ya creado podríamos evitar tocar apache con un Virtualhost del tipo:


ServerAdmin info@investic.net
DocumentRoot "/var/www/drupal_base"
ServerName nuevodominio.es
ServerAlias *.nuevodominio.es
RewriteEngine On
RewriteOptions inherit


Options FollowSymLinks MultiViews
AllowOverride All
Order allow,deny
Allow from all


Caso 2º
Si es un nuevo dominio hay que crear un VirtualHost nuevo, activar el sitio

a2ensite nuevositio

y reiniciar apache

#apache2ctl restart

Problemas con los permisos de los grupos - CCK Field Permissions

Módulo: CCK Field Permissions

Si tras quitarle los permisos a un grupo de un cck te sigue saliendo, debes utilizar el parche que adjuntamos.

Basado en el artículo: Problem with field groups

taxonomy_limit y taxonomy_super_select incompatibles, Aviso cocina

Hola hoy nuestra receta es más bien una recomendación, momentánea de incompatibilidades a la hora de mezclar sabores.

Por un lado tenemos el taxonomy_super_select un modulo vistoso y practico que permite plegar y desplegar una jerarquía de términos siempre y cuando esa jerarquía este marcada con selección múltiple. Este módulo hace mas amigable la inserción de datos
Y por el otro lado tenemos el modulo taxonomy_limit que limita el número de selecciones posibles de una taxonomía con opciones múltiples, asocias a un tipo de contenidos el limite incluso permitiendo definir el mensaje de error.

Bueno pues esto es como mezclar vinagre de vino con azucar, son sabores incompatible.

Por de pronto estos dos módulos no casan

Vim para drupal (vitrocerámica o gas)

Todo cocinero que se precie tiene sus preferencias, pero estas preferencias en ocasiones rallan la manía. Dentro de las manías mas recurrentes de un cocinero esta en la elección de sus herramientas, Karlos Argiñano siempre habla de que un cuchillo estilo Iberico nunca se podrá comparar con uno de esos Japoneses, o sin ir mas lejos la mejor cocinera del mundo, mi madre, simpre dice que para el bakalao nada mejor que el GAS que con la vitro no queda igual.

Nosotros los cocineros de drupal también tenemos nuestras manías y discusiones una de las mas clasicas es el entorno de desarrollos de nuestros programas. Es como una seña de identidad. Bueno yo soy de los raros que usan VIM, he probado de todo, Quanta, kate, el glotón del eclipse, pero siempre vuelvo al único e inigualable Vi Mejorado.

Para usar Vim como entorno de desarrollo he ido pillando elementos de configuración que pego aquí:

set expandtab
set tabstop=2
set shiftwidth=2
set autoindent
set smartindent
set encoding=utf-8
set paste

if has("autocmd")
" Drupal *.modules files.
augroup module
autocmd BufRead *.module set filetype=php
augroup END
augroup engine
autocmd BufRead *.engine set filetype=php
augroup END
augroup profile
autocmd BufRead *.profile set filetype=php
augroup END
endif

Crea un fichero .vimrc o edita el que tengas en tu home y entonces podrás ver los ficheros de tipo module, engine, y profile, como si fueran php, además de esto los tabulados serán de dos caracteres como dice la norma de estilo de drupal codificado en utf-8 y con la orden "set paste" podrás pegar sin problemas cualquier código.

No importa tanto el entorno con el que se programe, lo que importa es la convicción con la que se usa.

Salgamos del armarios, orgullo friki YO USO VIM.

Bueno coineros y cocineras Otro día hablare más sobre como usar Vim para drupal

Vistas embebidas

Cuando hay dos tipos de contenidos relacionados entre ellos, muchas veces nos gustaría que en el mismo nodo se pudiese ver también algunos datos de los relacionados.

Ésto se puede conseguir de varias formas, empezando por las vistas con argumentos y usando éstas en los paneles.. lo único que conlleva al problema de ir creando menús y paneles a medida.. Por lo que la mejor idea es la de las vistas embebidas.

Pasos para crear vistas embebidas (en este ejemplo el tipo de contentido "reunión" dependerá de "proyecto"):

  1. Crear el tipo de contenido proyecto.
  2. Crear el tipo de contenido reunión, y un campo tipo nodereference hacia "proyecto".
  3. Crear la vista de las reuniones, la que se unirá a los nodos tipo proyecto:
    • Tipo página
    • Cómo se quiera mostrar los datos, resumen, lista..
    • Argumentos: el campo nodereference
    • Filtro: Tipo de contenido- reunión
  4. Crear un node-proyectos.tpl.php e introducir el siguiente código
    <?php
       
    // cargar los  'metadata'
       
    global $current_view;
       
    // define el nid del nodo como el argumento
       
    $current_view->args[0]=$node->nid;
       
    // selecciona la vista para la view1
       
    $view1 = views_get_view('nombre_de_la_vista');                    
       
    // Añade clase
       
    print '<div class="clase_vista">';
         
    // El titulo de la vista incrustada
         
    print '<h2>' . 'Título' . '</h2>';
         
    // envia los argumentos de la vista y pinta el resultado en el contenido
         
    $vista = (views_build_view('embed', $view1, $current_view->args, false,
    false));
          if (
    $vista) { print $vista; }
          else { print
    'No hay ...'; }
        print
    '</div>';
     
    ?>

      

Y ya está, y de esta forma se pueden incrustar todas las vistas que se desean en los tipos de contenidos

En los casos en los que se añadan bastantes vistas (un ejemplo reuniones, documentos, tareas..) para poder acceder rápidamente al apartado que nos interese recomendamos la utilización de anclas.
Al comienzo del documento se pondrian los enlaces:

  <div class="proyectos_anclas" >
     <a href="#documentos">Documentos</a>
     <a href="#tareas">Tareas</a>
     <a href="#reuniones">Reuniones</a>
     <a href="#bonos">Bonos</a>
   </div>

y por encima del código de la vista se pondría la llamada
?> <div class="proyectos_anclas_titulos">  <a name="tareas">Tareas</a> </div> <?php

 

Basado en el artículo:
context-sensitive embedded views

Ejemplo:
Ejemplo vistas embebidas