Contenido

Creación de un módulo Drupal III

Qué vamos a hacer

En esta ocasión me voy a dedicar a arreglar los estropicios que hice anteriomente :D

Además, voy a añadir enlaces para eliminar los feeds (como me han solicitado) y también vamos a redirigir al usuario a la página principal después de añadir un feed (como también me han solicitado).

También añadiremos un mail al usuario que inserta el mensaje, por si no está registrado. En caso de que esté registrado, guardaremos una referencia al mismo.

Drupal

Qué se explica aquí

En esta ocasión veremos cómo:

  • Redirigir al usuario a la página que deseemos.
  • Ordenación de tablas.
  • Expresiones regulares.

Notas previas

En la primera parte del tutorial drupal ya insistí en que sólo se debe abrir el tag de <?php, y no se debe cerrar con ?>. Dicho esto, continuamos.

Modificando la BBDD

Añadimos el campo usermail. Además, modificamos el campo “uid” para que referencie al usuario si éste hizo login.

1
2
3
4
5
6
function feedback_update_6102() {
  $ret = array();
  db_add_field ( $ret, 'feedback_messages', 'usermail', array ( 'type' => 'text' ) );
  db_change_field ( $ret, 'feedback_messages', 'uid', 'uid', array ( 'type'=> 'int', 'unsigned'=>TRUE ) );
  return $ret;
}

Fe de erratas

El primer error fue la contabilización de feeds. Si miráis el tutorial Creación de un módulo Drupal (II)_, veréis la siguiente línea (función _feedback_count):

1
$query = "SELECT count(id) as total from {feedback_messages} fm where fm.read != 1";

Bueno, pues está mal. Lo correcto es lo siguiente:

1
$query = "select count(*) from drupal6.feedback_messages fm where isnull (fm.read) or fm.read != 1";

Como véis, comprobamos que no sea nulo, ya que en ese caso no estaba contabilizando correctamente.

El segundo error cometido es que los set_error deben realizarse sobre un campo. Así, en el primer tutorial, donde aparecen los set_error, están mal. Realmente no veremos la diferencia si no la conocemos: Si lo hacemos bien, los campos indicados se marcarán en rojo (depende del tema) indicando que el problema se encuentra en ése campo. De esta manera, quedarían así (función feedback_message_form_submit):

1
form_set_error ( 'feedback', t( "An error has happened. Your feedback has not been sent." ) );

Veremos la función completa cuando añadamos más cosas.

Y ya, como error menor, deciros que las etiquetas ‘Date’ y ‘User’ estaban cambiadas en la función feedback_admin.

Al final de este tutorial, pondré todo seguido para que podáis aclararos.

Modificando funciones

Primero vamos con lo más sencillo de todo: Queremos que cuando alguien meta un feed, que vuelva a la pantalla de inicio. Asumiré que la página de inicio es ?q=node, por lo que basta con indicarle:

1
drupal_goto ( 'node' );

A continuación, no sé si notásteis que la tabla con todos los mensajes no se ordena al pulsar las columnas. Esto nos puede venir bien para poder agrupar los mensajes no leídos, para ordenar por fecha, para agrupar los mensajes sin contenido, etc. ¡¡ Y es tan sencillo !! Basta con realizar un cambio durante la consulta, así que en feedback_admin:

1
2
3
$query = "SELECT fm.id, u.name, fm.indate, fm.message FROM {feedback_messages} fm, {users} u WHERE fm.uid=u.uid";
$query .= tablesort_sql ( $header );
$queryResult =  db_query ( $query );

Con eso le decimos a drupal que nos ordene la tabla. Ésa es una de las gracias de usar los headers en una tabla a parte, y por eso los definimos antes de realizar la consulta.

Añadiendo un mail

En las modificaciones de la base de datos, añadimos el campo usermail. Ahora vamos a usarlo. Necesitaremos que el usuario lo inserte, así que tenemos que modificar feedback_message_form:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function feedback_message_form ()
{
  global $user;
  $mail = "";

  if ( $user->uid != 0 )
    $mail = $user->mail;

  $form = array
  (
    'feedback' => array
    (
      '#type' => 'fieldset',
      '#title' => t( 'Feedback' ),
      'mail' => array ('#type' => 'textfield', "#title"=>"E-Mail", "#default_value" => $mail,
                "#description"=>"If you want any answer, please, tell me your mail. It would not be shown anywhere." ),
      'message' => array ( '#type' => 'textarea', "#description"=>"Write here your message" ),
      'submit' => array ( '#type' => 'submit',  '#value' => t('Submit'),  ),
    ),
  );

  return $form;
}

Como veréis, esta función tiene un añadido: si el usuario ha hecho login, rellenamos el campo con el mail que puso para su usuario. Así le ahorramos trabajo. El UID del usuario no es necesario que lo metamos en el formulario, ya que podemos recuperarlo directamente de la variable global.

Las validaciones también cambian, ya que no sólo vamos a comprobar que el mensaje no esté vacío, sino que queremos hacer más cosas. Queremos que, si el usuario hizo login, entonces el campo de e-mail no es obligatorio. Si no lo hizo, entonces sí que lo es. Y el e-mail tiene que parecer un e-mail, es decir, tener su arroba y demás:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
function feedback_message_form_validate ( $form, &$form_state )
{
  global $user;

  $message = $form_state['values']['message'];
  $mail    = $form_state['values']['mail'];
  $validmail = preg_match ("/^[^0-9][A-z0-9_]+([.][A-z0-9_]+)*[@][A-z0-9_]+([.][A-z0-9_]+)*[.][A-z]{2,4}$/" , $mail );

  if ( $mail == '' && $user->uid == 0 )
    form_set_error ( 'mail', t('You are not a registered user. Please, insert your e-mail.') );
  if ( $mail != '' && ! $validmail )
    form_set_error ( 'mail', t('The mail does not like an e-mail address.') );
  if ( $message == '' )
    form_set_error ( 'message', t('Message cannot be empty.'));

  return $form;
}

Aquí hemos introducido la creación de una expresión regular. Explicada brevemente, estamos comprobando si encaja el mail con un patrón dado. La expresión regular es bastante compleja, así que sólo comentaré lo más básico de todo:

  • Lo que va entre corchetes, significa “uno de estos”. Ej: [A-z0-9_] significa que queremos una letra mayúscula o minúscula, un número o un guión bajo.
  • Lo que va entre corchetes pero comienza por “^”, significa “ninguno de estos”. Ej. [^0-9] significa “algo que no sea un número”.
  • El asterisco significa “lo anterior se puede repetir 0 o más veces”. Ej: [0-9]* significa que puede no haber nada o bien un número indeterminado de números.
  • El símbolo de suma significa “lo anterior se puede repetir 1 o más veces”. Ej: [0-9]+ significa que puede haber un número indeterminado de números, pero debe aparecer al menos uno.
  • Los paréntesis permiten agrupar cosas para aplicarle otros símbolos.
  • Las llaves implican la multiplicidad exacta. Ej: [A-z]{2} significa “dos letras”. [A-z]{2,4} significa “entre 2 y 4 letras”.

Habitualmente, crear una expresión regular es mucho más sencillo de lo que parece, pero modificar una que ya existe suele ser bastante complicadete :-D

Bueno, y nos queda la inserción:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
function feedback_message_form_submit ( $form, &$form_state )
{
  global $user;
  $userid = NULL;
  if ( $user )
    $userid = $user->uid;
  $message = $form_state['values']['message'];
  $mail = $form_state['values']['mail'];

  $query = "INSERT into {feedback_messages} ( uid, message, indate, usermail ) values ( %d, '%s', now(), '%s' ) ";
  $queryResult = db_query ( $query, $userid, $message, $mail );

  if ( db_affected_rows() )
  {
    drupal_set_message ( t ( "Thank you for your feedback." ) );
    drupal_goto ( 'node' );
  }
  else
    form_set_error ( 'feedback', t( "An error has happened. Your feedback has not been sent." ) );
}

Como ya sabemos redirigir, si todo va bien, nos iremos a la página principal :-D

Ya que tenemos el mail, lo suyo es que lo veamos desde la tabla principal de feeds:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function feedback_admin ( $messageid=null )
{
  $content = '';

  if ( $messageid != null )
  {
    $content .= drupal_get_form ( 'feedback_messageadmin_form', $messageid );
    $content .= "";
  }

  $header = array
  (
    array('data' => t('Date'), 'field' => 'indate', 'sort' => 'desc'),
    array('data' => t('User'), 'field' => 'name'),
    array('data' => t('email'), 'field'=>'mail'),
    array('data' => t('Message'), 'field' => 'message'),
    array('data' => t('Read'), 'field'=>'fm.read'),
  );

  $query = "SELECT fm.id, u.uid as uid, u.name, fm.usermail, fm.indate, fm.message, fm.read FROM {feedback_messages} fm, {users} u WHERE fm.uid=u.uid";
  $query .= tablesort_sql ( $header );
  $queryResult =  db_query ( $query );

  $rows = array ();
  while ( $message = db_fetch_object ( $queryResult ) )
  {
    $row = array ();
    $row['indate'] = $message->indate;
    $row['name'] = $message->uid != 0 ? '' . $message->name . '' : $message->name;
    $row['mail'] = $message->usermail;
    $row['message'] = $message->message;
    $row['read'] = $message->read;
    $row['edit'] = l ( t('edit'), "feedback/adminmessages/" . $message->id );
    $rows[] = $row;
  }

  $content .= theme_table($header, $rows);
  return $content;
}

¡¡¡ Mucho ojo, porque a esta función aún tenemos que añadirle una línea para el borrado !!!

Además he añadido una cosa nueva. Si pulsáis sobre el nombre de uno de los usuarios, os redirigirá a la página personal del mismo.

Borrando

Ahora vamos a añadir una nueva operación: el borrado.

La forma de realizarlo va a ser similar a como está hecha la edición, con la diferencia de que vamos a cambiar el botón por uno de “eliminar”. Así que resulta fácil realizar este paso, aunque tendrá sus inconvenientes :-D

Comenzamos como siempre: permisos, menú, función principal y formularios.

No necesitamos más permisos de los que ya tenemos, así que en la función de menú (feedback_menu), añadimos lo siguiente:

1
2
3
4
5
6
7
8
$items['feedback/delete/%'] = array
  (
    'title' => 'Feedback delete',
    'page callback' => 'feedback_delete',
    'access arguments' => array('view messages'),
    'page arguments' => array ( 2 ),
    'type' => MENU_CALLBACK,
  );

Ahora creamos la función principal:

1
2
3
4
5
6
7
function feedback_delete ( $messageid=null )
{
  $content = '';
  $content .= drupal_get_form ( 'feedback_delete_form', $messageid );

  return $content;
}

Muy similar a feedback_message. Y también creamos el formulario:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
function feedback_delete_form ( $form, $messageid )
{
  $query = "SELECT fm.message, fm.read, fm.indate, u.name FROM {feedback_messages} fm, {users} u WHERE fm.id=%d and u.uid=fm.uid";
  $queryResult = db_query ( $query, $messageid );
  $message = db_fetch_object ( $queryResult );

  $form = array
    (
      'feedback' => array
      (
        '#type' => 'fieldset',
        '#title' => t( 'Feedback from ' . $message->name .' sended on ' . $message->indate ),
        'messageid' => array ( '#type' => 'hidden', "#default_value" => $messageid ),
        'message' => array ( '#type' => 'textarea', "#default_value" => $message->message, "#disabled" => TRUE ),
        'read'  => array ( '#type'=> 'checkbox', "#title" => "Read","#default_value" => $message->read, "#disabled" => TRUE ),
        'submit' => array ( '#type' => 'submit',  '#value' => t('Delete forever'),  ),
      ),
    );
    return $form;
}

function feedback_delete_form_submit ( $form, &$form_state )
{
  $messageid = $form_state['values']['messageid'];

  $query = "DELETE FROM {feedback_messages} where id=%d";
  $queryResult = db_query ( $query, $messageid );

  if(db_affected_rows()){
    drupal_set_message ( t ( "Message deleted" ) );
  }

  drupal_goto ('/feedback/adminmessages');
}

Como véis, me he saltado la validación, ya que no hay nada que validar. El formulario es muy parecido al de feedback_messageadmin_form, pero con la diferencia de que el campo “read” también es de sólo lectura.

Lo que nos queda es poder llegar a este formulario. Para llegar, dijimos que usaríamos un sistema similar al del botón “edit”, así que eso mismo vamos a hacer: En la función feedback_admin, el final quedará así:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
function feedback_admin( $messageid=null ) {
    [...]
    $row['edit'] = l ( t('edit'), "feedback/adminmessages/" . $message->id );
    $row['delete'] = l ( t('delete'), "feedback/delete/" . $message->id );
    $rows[] = $row;
  }

  $content .= theme_table($header, $rows);
  return $content;
}

Dos palabras

Últimamente estoy recibiendo muchas consultas sobre cómo hacer tal o cual cosa en drupal. La verdad es que no esperaba tener “tanto” éxito con los tutoriales… casi ni explico nada, sólo he desglosado un ejercicio en partes tan pequeñas que no dé miedo atacarlas.

Así que tan sólo puedo deciros una cosa: ¡¡ Muchas gracias !! ;)

Más tutoriales

Este tutorial es la continuación de una serie de tutoriales relacionados con Drupal. Podéis consultar cualquiera de ellos:

Código

Aquí tenéis todo el código necesario:

feedback.info

1
2
3
4
; $Id$
name = "MagMax Feedback"
description = "Proporciona un sistema de feedbacks fácil para drupal"
core = 6.x

feedback.install

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<?php
/*
Copyright 2009 Miguel Ángel García Martínez

  'Feedback' is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

  'Feedback' is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
along with 'Feedback' (maybe in file "COPYING"); if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/


function feedback_schema ()
{
  $schema['feedback_messages'] = array
  (
    'description' => t('Tabla para mensajes de retroalimentacion'),
    'fields' => array
    (
      'id' => array
      (
        'description' => t('Identificador de mensaje'),
        'type' => 'serial',
        'unsigned' => TRUE,
        'not null' => TRUE,
      ),
      'uid' => array
      (
        'description' => t('Identificador del usuario que realiza el feedback'),
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => FALSE,
      ),
      'message' => array
      (
        'description' => t('Mensaje de feedback'),
        'type' => 'text',
        'not null' => TRUE,
      ),
      'indate' => array
      (
        'description' => t('Fecha en la que se crea el comentario'),
        'type' => 'datetime',
        'not null' => TRUE,
      ),
    ),
    'primary key' => array('id'),
  );
  return $schema;
}

function feedback_update_6100() {
  $ret = array();
  db_add_field($ret, 'feedback_messages', 'read', array('type' => 'int', 'size' => 'tiny'));
  return $ret;
}

function feedback_update_6103() {
  $ret = array();
  db_add_field ( $ret, 'feedback_messages', 'usermail', array ( 'type' => 'text' ) );
  db_change_field ( $ret, 'feedback_messages', 'uid', 'uid', array ( 'type'=> 'int', 'unsigned'=>TRUE ) );
  return $ret;
}

function feedback_install() {
  // Create my tables.
  drupal_install_schema('feedback');
}

function feedback_uninstall() {
  // Drop my tables.
  drupal_uninstall_schema('feedback');
}

feedback.module

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
<?php
/*
Copyright 2009 Miguel Ángel García Martínez

  'Feedback' is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

  'Feedback' is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
along with 'Feedback' (maybe in file "COPYING"); if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
/**
* Implements hook_help().
*/
function feedback_help ( $path, $arg )
{
  $output=''; // para construir la salida
  switch ( path )
  {
    case 'admin/help#feedback':
      $output .= '' . t('Módulo que permite la inserción de mensajes de feedback.') . '';
      break;
  }
  return $output;
}

/**
* Implements hook_perm().
*/
function feedback_perm ()
{
  return array ('send message', 'view messages');
}

/**
* Implementation of hook_block().
*/
function feedback_block ( $op = 'list', $delta = 0, $edit = array() )
{
  if ( $op == "list")
  {
      $blocks = array();
      $blocks[0]["info"] = t('Feedback');
      $blocks[1]["info"] = t('New Feedbacks');
      return $blocks;
  }
  else if ( $op == "view" )
  {
      $content = '';
      $block = array();
      switch ( $delta )
      {
        case 0:
          $block['subject'] = t('Feedback');

          $options = array( "attributes" => array("title" => t("Sends a feedback message") ) );
          $link = l( t("New Feedback"), "feedback/message", $options );
          $content .= '' . $link . "";
          break;
        case 1:
          $block['subject'] = t('Feedback Messages');

          $options = array( "attributes" => array("title" => t("Shows feedback messages") ) );
          $title = t("There are @total new feeds", array ( '@total' => _feedback_count() ) );
          $link = l( $title , "feedback/adminmessages", $options );
          $content .= '' . $link . "";
          break;
      }
      $block['content'] = $content;
      return $block;
  }
}

/**
* Implementation of hook_menu().
*/
function feedback_menu ( )
{
  $items = array();

  $items['feedback/message'] = array
  (
    'title' => 'Feedback',
    'page callback' => 'feedback_message',
    'access arguments' => array('send message'),
    'type' => MENU_CALLBACK,
  );

  $items['feedback/adminmessages/%'] = array
  (
    'title' => 'Feedback admin',
    'page callback' => 'feedback_admin',
    'page arguments' => array ( 2 ),
    'access arguments' => array('view messages'),
    'type' => MENU_CALLBACK,
  );
  $items['feedback/adminmessages'] = array
  (
    'title' => 'Feedback admin',
    'page callback' => 'feedback_admin',
    'access arguments' => array('view messages'),
    'type' => MENU_CALLBACK,
  );

  $items['feedback/delete/%'] = array
  (
    'title' => 'Feedback delete',
    'page callback' => 'feedback_delete',
    'page arguments' => array ( 2 ),
    'access arguments' => array('view messages'),
    'type' => MENU_CALLBACK,
  );

  return $items;
}

function feedback_message ()
{
  $content = '';

  $content .= drupal_get_form ( 'feedback_message_form' );

  return $content;
}

function feedback_message_form ()
{
  global $user;
  $mail = "";

  if ( $user->uid != 0 )
    $mail = $user->mail;

  $form = array
  (
    'feedback' => array
    (
      '#type' => 'fieldset',
      '#title' => t( 'Feedback' ),
      'mail' => array ('#type' => 'textfield', "#title"=>"E-Mail", "#description"=>"If you want any answer, please, tell me your mail. It would not be shown anywhere.", "#default_value" => $mail ),
      'message' => array ( '#type' => 'textarea', "#description"=>"Write here your message" ),
      'submit' => array ( '#type' => 'submit',  '#value' => t('Submit'),  ),
    ),
  );

  return $form;
}

function feedback_message_form_validate ( $form, &$form_state )
{
  global $user;

  $message = $form_state['values']['message'];
  $mail    = $form_state['values']['mail'];
  $validmail = preg_match ("/^[^0-9][A-z0-9_]+([.][A-z0-9_]+)*[@][A-z0-9_]+([.][A-z0-9_]+)*[.][A-z]{2,4}$/" , $mail );

  if ( $mail == '' && $user->uid == 0 )
    form_set_error ( 'mail', t('You are not a registered user. Please, insert your e-mail.') );
  if ( $mail != '' && ! $validmail )
    form_set_error ( 'mail', t('The mail does not like an e-mail address.') );
  if ( $message == '' )
    form_set_error ( 'message', t('Message cannot be empty.'));

  return $form;
}

function feedback_message_form_submit ( $form, &$form_state )
{
  global $user;
  $userid = NULL;
  if ( $user )
    $userid = $user->uid;
  $message = $form_state['values']['message'];
  $mail = $form_state['values']['mail'];

  $query = "INSERT into {feedback_messages} ( uid, message, indate, usermail ) values ( %d, '%s', now(), '%s' ) ";
  $queryResult = db_query ( $query, $userid, $message, $mail );

  if ( db_affected_rows() )
  {
    drupal_set_message ( t ( "Thank you for your feedback." ) );
    drupal_goto ( 'node' );
  }
  else
    form_set_error ( 'feedback', t( "An error has happened. Your feedback has not been sent." ) );
}


function feedback_admin ( $messageid=null )
{
  $content = '';

  if ( $messageid != null )
  {
    $content .= drupal_get_form ( 'feedback_messageadmin_form', $messageid );
    $content .= "";
  }

  $header = array
  (
    array('data' => t('Date'), 'field' => 'indate', 'sort' => 'desc'),
    array('data' => t('User'), 'field' => 'name'),
    array('data' => t('email'), 'field'=>'mail'),
    array('data' => t('Message'), 'field' => 'message'),
    array('data' => t('Read'), 'field'=>'fm.read'),
  );

  $query = "SELECT fm.id, u.uid as uid, u.name, fm.usermail, fm.indate, fm.message, fm.read FROM {feedback_messages} fm, {users} u WHERE fm.uid=u.uid";
  $query .= tablesort_sql ( $header );
  $queryResult =  db_query ( $query );

  $rows = array ();
  while ( $message = db_fetch_object ( $queryResult ) )
  {
    $row = array ();
    $row['indate'] = $message->indate;
    $row['name'] = $message->uid != 0 ? '' . $message->name . '' : $message->name;
    $row['mail'] = $message->usermail;
    $row['message'] = $message->message;
    $row['read'] = $message->read;
    $row['edit'] = l ( t('edit'), "feedback/adminmessages/" . $message->id );
    $row['delete'] = l ( t('delete'), "feedback/delete/" . $message->id );
    $rows[] = $row;
  }

  $content .= theme_table($header, $rows);
  return $content;
}

/** Devuelve el número de feeds creados en la última semana
*/
function _feedback_count ()
{
  $query = "SELECT count(id) as total from {feedback_messages} fm where fm.read != 1 or isnull(fm.read)";
  $queryResult =  db_query ( $query );
  $result = db_fetch_object ( $queryResult ) ;

  return $result->total;
}

function feedback_messageadmin_form ( $form, $messageid )
{
  $query = "SELECT fm.message, fm.read, fm.indate, u.name FROM {feedback_messages} fm, {users} u WHERE fm.id=%d and u.uid=fm.uid";
  $queryResult = db_query ( $query, $messageid );
  $message = db_fetch_object ( $queryResult );

  $form = array
    (
      'feedback' => array
      (
        '#type' => 'fieldset',
        '#title' => t( 'Feedback from ' . $message->name .' sended on ' . $message->indate ),
        'messageid' => array ( '#type' => 'hidden', "#default_value" => $messageid ),
        'message' => array ( '#type' => 'textarea', "#default_value" => $message->message, "#disabled" => TRUE ),
        'read'  => array ( '#type'=> 'checkbox', "#title" => "Read","#default_value" => $message->read ),
        'submit' => array ( '#type' => 'submit',  '#value' => t('Submit'),  ),
      ),
    );
    return $form;
}

function feedback_messageadmin_form_submit ( $form, &$form_state )
{
  $messageid = $form_state['values']['messageid'];
  $read      = $form_state['values']['read'];

  $query = "UPDATE {feedback_messages} fm set fm.read=%d where fm.id=%d";
  $queryResult = db_query ( $query, $read, $messageid );

  drupal_goto ('/feedback/adminmessages');
}


function feedback_delete ( $messageid=null )
{
  $content = '';
  $content .= drupal_get_form ( 'feedback_delete_form', $messageid );

  return $content;
}

function feedback_delete_form ( $form, $messageid )
{
  $query = "SELECT fm.message, fm.read, fm.indate, u.name FROM {feedback_messages} fm, {users} u WHERE fm.id=%d and u.uid=fm.uid";
  $queryResult = db_query ( $query, $messageid );
  $message = db_fetch_object ( $queryResult );

  $form = array
    (
      'feedback' => array
      (
        '#type' => 'fieldset',
        '#title' => t( 'Feedback from ' . $message->name .' sended on ' . $message->indate ),
        'messageid' => array ( '#type' => 'hidden', "#default_value" => $messageid ),
        'message' => array ( '#type' => 'textarea', "#default_value" => $message->message, "#disabled" => TRUE ),
        'read'  => array ( '#type'=> 'checkbox', "#title" => "Read","#default_value" => $message->read, "#disabled" => TRUE ),
        'submit' => array ( '#type' => 'submit',  '#value' => t('Delete forever'),  ),
      ),
    );
    return $form;
}

function feedback_delete_form_submit ( $form, &$form_state )
{
  $messageid = $form_state['values']['messageid'];

  $query = "DELETE FROM {feedback_messages} where id=%d";
  $queryResult = db_query ( $query, $messageid );

  if(db_affected_rows()){
    drupal_set_message ( t ( "Message deleted" ) );
  }

  drupal_goto ('/feedback/adminmessages');
}