Form dinamica in tabella per content type

9 contenuti / 0 new
Ultimo contenuto
Form dinamica in tabella per content type

Salve,

Sto realizzando un content type 'torneo' il quale prevede i seguenti dati:

  • Titolo
  • Periodo (tre select per mesi di inizio e fine e anno)
  • Classifica

Il problema sorge per la parte 'Classifica'.
Questa parte di form prevede una serie di campi text (Punti, BUK, e B.S.) per valori numerici float per ogni utente registrato al sito. Gli utenti registrati sono i membri del circolo.

Pensavo di organizzare la form con un ciclo, e di inserire il tutto in una tabella; quindi avendo le seguenti colonne: Nominativo, Punti, BUK, B.S. e avendo ogni riga riferita ad ogni giocatore.
Per fare un esempio, una cosa simile la trovate all'indirizzo admin/user/user, appare una tabella ordinabile di utenti.
Ho provato ad adattare la funzione preposta a questo lavoro per le mie esigenze, ma a video non riesco ad ottenere la form in tabella.

Via chat ho ricevuto un aiuto che però non ha funzionato come sperato; posto il codice da lì prodotto.

<?php
/**
 * Implementation of hook_form
 */
function gs_content_type_form(&$node, $form_state) {
 
$type = node_get_types('type', $node);
  if (
$type->type == 'torneo') {
    if (
$type->has_title) {
     
$form['title'] = array(
       
'#type' => 'textfield',
       
'#title' => check_plain($type->title_label),
       
'#required' => TRUE,
       
'#default_value' => $node->title,
       
'#weight' => -5,
      );
    }
   
$data = new Data();
   
$form['inizio'] = array(
     
'#type' => 'select',
     
'#title' => t("Mese d'inizio"),
     
'#default_value' => $data->get_mese_corrente(),
     
'#options' => $data->get_mesi(),
     
'#description' => t("Selezione il mese di inizio"),
    );
   
$form['fine'] = array(
     
'#type' => 'select',
     
'#title' => t("Mese di fine"),
     
'#default_value' => $data->get_mese_corrente(),
     
'#options' => $data->get_mesi(),
     
'#description' => t("Selezione il mese di conclusione"),
    );
   
$form['anno'] = array(
     
'#type' => 'select',
     
'#title' => t("Anno"),
     
'#default_value' => $data->get_anno_corrente(),
     
'#options' => $data->get_anni(),
     
'#description' => t("Selezione l'anno"),
    );
    if (
$type->has_body) {
     
// In Drupal 6, we can use node_body_field() to get the body and filter
      // elements. This replaces the old textarea + filter_form() method of
      // setting this up. It will also ensure the teaser splitter gets set up
      // properly.
      //    $form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count);
   
}
  }
 
$sql = 'SELECT DISTINCT u.uid, u.name FROM {users} u WHERE u.uid != 0 AND u.status = 1 ';
 
$result = db_query($sql);
  while (
$account = db_fetch_object($result)) {
   
$form['punti'. $account->uid] = array(
     
'#type' => 'textfield',
     
'#title' => 'Punti',
     
'#default_value' => 0,
     
'#description' => t("Il punteggio ottenuto dal giocatore"),
     
'#size' => 5,
     
'#maxlength' => 5
   
);
   
$form['buk'. $account->uid] = array(
     
'#type' => 'textfield',
     
'#title' => 'BUK',
     
'#default_value' => 0,
     
'#description' => t("Il BUK ottenuto dal giocatore"),
     
'#size' => 5,
     
'#maxlength' => 5
   
);
   
$form['bs'. $account->uid] = array(
     
'#type' => 'textfield',
     
'#title' => 'B.S.',
     
'#default_value' => 0,
     
'#description' => t("Il B.S. ottenuto dal giocatore"),
     
'#size' => 5,
     
'#maxlength' => 5
   
);
  }
 
$form['#theme'] = 'gs_torneo_table';
  return
$form;
}
/**
 * Implementation of hook_theme
 */
function gs_content_type_theme($existing, $type, $theme, $path) {
  return array(
   
'gs_torneo_table' => array('arguments' => array('form' => array())));
}
function
theme_gs_torneo_table($form) {
 
$header = array('Giocatore', 'Categoria', 'Punti', 'BUK', 'B.S.');
 
$data = array();
  foreach (
element_children($form) as $element) {
    if (
substr($element, 0, 4) == 'text') {
    
$data[] = array(drupal_render($element), );
     }
  }
 
$output = '';
 
$output .= theme('table', $header, $data);
 
$output .= drupal_render($form);
  return
$output;
}
 
?>

Non appena implementate queste istruzioni, Drupal ha iniziato a mandarmi dei warning poiché non riusciva a trovare il file block.tpl.php all'interno della directory del modulo - io solitamene i tpl li metto nella directory del theme -; inoltre, tali istruzioni non riescono a mettermi in tabella la suddetta form.

In fondo, il problema è puramente strutturale. A me serve creare una form dinamicamente all'interno di una tabella, magari con le header della stessa cliccabili per poterla ordinare, esattamente come nel link admin/user/user. Niente di alieno come CCK, et similia.

Ho utilizzato il seguente hook per definire il content type:

<?php
/**
 * Implementation of hook_node_info
 */
function gs_content_type_node_info() {
  return array(
   
'torneo' => array(
     
'name' => t('Torneo'),
     
'module' => 'gs_content_type',
     
'description' => "Organizza i tornei giocati dal Circolo Galatea Scacchi.",
     
'help' => t("Elenca il titolo e il periodo del torneo, poi per ogni partecipante il punteggio, categoria, BUK e BS.<br />La classifica finale sarà poi creata automaticamente."),
     
'has_title' => true,
     
'title_label' => t("Title"),
     
'has_body' => false,
    ));
}
 
?>

L'obiettivo finale è quello di poter creare un nuovo torneo e assegnare per ogni giocatore il proprio punteggio. Nel momento in cui l'utente naviga tra i tornei, il sito è in grado di riprendere il torneo richiesto e a stilare la classifica finale.

Grazie.

risolto:

<?php
/**
 * Implementation of hook_form
 */
function gs_content_type_form(&$node, $form_state) {
 
$type = node_get_types('type', $node);
  if (
$type->type == 'torneo') {
    if (
$type->has_title) {
     
$form['title'] = array(
       
'#type' => 'textfield',
       
'#title' => check_plain($type->title_label),
       
'#required' => TRUE,
       
'#default_value' => $node->title,
       
'#weight' => -5,
      );
    }
   
$data = new Data();
   
$form['inizio'] = array(
     
'#type' => 'select',
     
'#title' => t("Mese d'inizio"),
     
'#default_value' => $data->get_mese_corrente(),
     
'#options' => $data->get_mesi(),
     
'#description' => t("Selezione il mese di inizio"),
    );
   
$form['fine'] = array(
     
'#type' => 'select',
     
'#title' => t("Mese di fine"),
     
'#default_value' => $data->get_mese_corrente() + 3,
     
'#options' => $data->get_mesi(),
     
'#description' => t("Selezione il mese di conclusione"),
    );
   
$form['anno'] = array(
     
'#type' => 'select',
     
'#title' => t("Anno"),
     
'#default_value' => $data->get_anno_corrente(),
     
'#options' => $data->get_anni(),
     
'#description' => t("Selezione l'anno"),
    );
    if (
$type->has_body) {
     
// In Drupal 6, we can use node_body_field() to get the body and filter
      // elements. This replaces the old textarea + filter_form() method of
      // setting this up. It will also ensure the teaser splitter gets set up
      // properly.
//      $form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count);
   
}
  }
 
$header = array(
    array(
'data' => 'Giocatore', 'field' => 'u.name')
    , array(
'data' => 'Punti', 'title' => t("Il punteggio ottenuto dal giocatore"))
    , array(
'data' => 'BUK', 'title' => t("Il BUK ottenuto dal giocatore"))
    , array(
'data' => 'B.S.', 'title' => t("Il B.S. ottenuto dal giocatore"))
  );
 
$query = 'SELECT DISTINCT u.uid, u.name FROM {users} u WHERE u.uid != 0 AND u.status = 1 ';
 
$query .= tablesort_sql($header);
 
$query_count = ' SELECT COUNT(u.uid) FROM {users} u WHERE u.uid != 0 AND u.status = 1 ';
 
$result = pager_query($query, 50, 0, $query_count, array());
 
$form['users_data']['#tree'] = true;
 
$table = theme_table($header, array(null, null, null));
 
$table = str_replace('</table>', '', $table);
 
$table = str_replace('</tbody>', '', $table);
 
$form['users_data']['#prefix'] = $table;
 
$form['users_data']['#suffix'] = '</tbody></table>';
  while (
$account = db_fetch_object($result)) {
   
$form['users_data'][$account->uid]['giocatore'] = array(
     
'#value' => theme('username', $account),
     
'#prefix' => '<td>',
     
'#suffix' => '</td>'
   
);
   
$form['users_data'][$account->uid]['punti'] = array(
     
'#type' => 'textfield',
     
'#default_value' => '0.0',
     
'#size' => 5,
     
'#maxlength' => 5,
     
'#prefix' => '<td>',
     
'#suffix' => '</td>'
   
);
   
$form['users_data'][$account->uid]['buk'] = array(
     
'#type' => 'textfield',
     
'#default_value' => '0.0',
     
'#size' => 5,
     
'#maxlength' => 5,
     
'#prefix' => '<td>',
     
'#suffix' => '</td>'
   
);
   
$form['users_data'][$account->uid]['bs'] = array(
     
'#type' => 'textfield',
     
'#default_value' => '0.0',
     
'#size' => 5,
     
'#maxlength' => 5,
     
'#prefix' => '<td>',
     
'#suffix' => '</td></tr>'
   
);
  }
  return
$form;
}
?>

le altre soluzioni proposte dal precedente link non andavano e non ho approfondito: per ora mi sta bene così.

grazie dell'aiuto che mi avete dato in sti giorni, son riuscito a trovare la soluzione e a capire un po' di cose :)

Una volta (tanti anni fa) chiedevo al mio papà perchè parlava da solo quando faceva la barba - mi rispose che "era l'unica conversazione intelligente della giornata". Lo fai anche tu con i thread? ;-)
Grazie per la tua resoluzione alla tua problema - aiuta anche chi (come me) stava ascoltando e basta...

Più imparo, più dubito.

ah beh avevo chiesto aiuto sia qui che in chat e nel frattempo ho studiato da me il problema. visto che son arrivato ad una soluzione utile, ho pensato fosse corretto renderla nota, magari servirà ad altri, ma anche a me stesso, che magari dopo un po' di tempo potrei ricercare il thread :D

Sono alle prime armi sia con Drupal che con il php e mi limito ad osservare ed a cercare di capire qualcosa delle personalizzazioni che si trovano in giro. Il tuo articolo è ineressante per un piccolo progetto di iscrizioni on-line che ho in mente ma mi sfugge completamente le modalità di implementazione dell'istruzione: $data = new Data();
Ho cercato sia nelle api di drupal che nel manuale di php ma ovviamente non trovo nulla in quanto sembra un oggetto personalizzato (vedi le varie proprietà italianizzate) del quale manca la definizione. Potresti darmi qualche dritta di come poterlo implementare.
Ciao e Grazie

Quella è una classetta che ho fatto da me che implementa alcune funzioni php con alcune configurazioni che utilizzo di solito in questo progetto - ne escludo l'utilizzo al di fuori se non modificando come si deve -... Mi pare esista però sul repo di Drupal una serie di moduli che danno un supporto migliore nella gestione delle date, che ti consiglio di utilizzare vivamente.

Intanto, ti posto il code di questa classe, così comprendi il contesto:

<?php
class Data {
  private
$mesi = array(
   
1 => 'Gennaio'
   
, 2 => 'Febbraio'
   
, 3 => 'Marzo'
   
, 4 => 'Aprile'
   
, 5 => 'Maggio'
   
, 6 => 'Giugno'
   
, 7 => 'Luglio'
   
, 8 => 'Agosto'
   
, 9 => 'Settembre'
   
, 10 => 'Ottobre'
   
, 11 => 'Novembre'
   
, 12 => 'Dicembre');
  const
ANNO_INIZIALE = 1999;
  const
MESE = 'n';
  const
ANNO = 'Y';
  const
GIORNO = 'j';
  const
ORA = 'G';
  const
MINUTO = 'i';
  function
get_mesi($null = null) {
    if (!
is_null($null)) {
     
$mesi[0] = $null;
    }
    foreach (
$this->mesi as $numero => $mese) {
     
$mesi[$numero] = $mese;
    }
    return
$mesi;
  }
  function
get_mese_corrente() {
    return
date('n');
  }
  function
get_mese($mese = null) {
    if (
$mese >= 1 && $mese <= 12) {
      return
$this->mesi[$mese];
    }
    return
$this->mesi[$this->get_mese_corrente()];
  }
  function
get_anni($null = null) {
    if (!
is_null($null)) {
     
$anni[] = $null;
    }
    for (
$anno = self::ANNO_INIZIALE, $futuro = (int)date('Y') + 5; $anno <= $futuro; $anno++) {
     
$anni[$anno] = $anno;
    }
    return
$anni;
  }
  function
get_anno_corrente() {
   
$anni = $this->get_anni();
    return
array_search(date('Y'), $anni);
  }
  function
get_giorno_corrente() {
    return
date("j") - 1;
  }
  function
get_giorni($null = null) {
    if (!
is_null($null)) {
     
$giorni[] = $null;
    }
    for (
$i = 1; $i <= 31; $i++) {
     
$giorni[] = $i;
    }
    return
$giorni;
  }
  function
get_ora_corrente() {
    return
date("G") - 1;
  }
  function
get_ore($null = null) {
    if (!
is_null($null)) {
     
$ore[] = $null;
    }
    for (
$i = 0; $i <= 23; $i++) {
     
$ore[] = $i;
    }
    return
$ore;
  }
  function
get_minuto_corrente() {
    return
date("i");
  }
  function
get_minuti($null = null) {
    if (!
is_null($null)) {
     
$minuti[] = $null;
    }
    for (
$i = 0; $i <= 59; $i++) {
      if (
$i < 10) {
       
$i = "0". $i;
      }
     
$minuti[] = $i;
    }
    return
$minuti;
  }
}
?>

Ciao, sto sviluppando un nuovo conten type su drupal 6 per la gestione dei voti e dei pagellini degli studenti di una scuola.
Per farla breve mi sono servito dell'impostazione di tabella dinamica più o meno così come l'hai condivisa.
Tutto ok ma ho un problema quando vado a salvare il nodo:
nella tua hook_insert($node) come fai a prendere i valori dei campi $form['users_data'][$account->uid]['punti'], $form['users_data'][$account->uid]['buk'] e $form['users_data'][$account->uid]['bs']????
cioè io penso che vada rifatto un ciclo while come quello che crea la tabella con gli utenti e all'interno mettere una query INSERT, ma come faccio a passargli i valori dei campi suddetti???

Grazie dell'aiuto ma non ci riesco proprio

Beh intanto nella hook_insert gli arriva un oggetto $node, quindi prelevi i dati da lì per poi eseguire le tue insert.

L'organizzazione dei field e dei valori all'interno la decidi tu come meglio ti viene.
Ad esempio gestendo la form via hook_form(&$node, $form_state). Hai un oggetto $node (da utilizzare per non perdere i dati inseriti da un utente dopo un errore o un edit del nodo) e la $form_state (il nome parla da sé).

$form_state ha un hash 'values', dentro il quale cambiare poi le carte in tavola, o meglio, si fa nel submit, dopo che nel validate hai controllato la correttezza delle informazioni.
Tutto ciò te lo ritroverai nel $node della hook_insert, pronto pronto per eseguire le insert.

Ti consiglio di fare così: dopo la hook_form, implementa il validate e il submit e facci un bel var_dump($form_state['values']), e vedi da te che dati avrà. Fai anche con la hook_insert, che dati arrivano in ingresso.