
Pour ajouter des fonctionnalités, il est souvent nécessaire d'ajouter de nouvelles tables métier dans la base de données de Drupal. Pour mettre à jour ces enregistrements on aura besoin d'ajouter un CRUD (Create, Read, Update, Delete) à l'administration du site.
Au préalable on aura créé une table via l'installation d'un module.
Au programme :
- Créer une liste d'entités
- Créer un formulaire pour créer ou modifier une entité
- Créer un lien pour supprimer une entité
1. Comment créer une liste d'entités pour notre CRUD?
Pour créer une liste dans l'admin de Drupal, on va commencer par implémenter hook_menu dans le fichier mon_module.module pour avoir un lien "admin/mon_module/list" qui pointe vers le callback "mon_module_list" qui se trouve dans le fichier "mon_module.admin.inc".
/**
* Implements hook_menu().
*/
function mon_module_menu()
{
$items = array();
$items['admin/mon_module/list'] = array(
'title' => 'Liste des entités',
'description' => 'Voici la liste de mes entités.',
'page callback' => 'mon_module_list',
'page arguments' => array('_filter_list_form'),
'access arguments' => array('administrer site configuration'),
'file' => 'mon_module.admin.inc',
);
return $items;
}
Ensuite dans le fichier mon_module.admin.inc, on ajoute notre fonction mon_module_list.
/**
* Form builder
*/
function mon_module_list($form_state) {
$form = array();
$form['search'] = array(
'#type' => 'fieldset',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#title' => 'Filtrer les résultats',
'#attributes' => array('class' => array('container-inline')),
);
// Adds filter form to the build array.
$form_search = drupal_get_form('password_filter_form');
$form['search']['form'] = $form_search;
// Build the sortable table header.
// Add field to sort table
$header = array(
array('data' => t('id'), 'field' => 'id'),
array('data' => t('node_id'), 'field' => 'node_id'),
array('data' => t('title'), 'field' => 'title'),
array('data' => t('password')),
array('data' => t('user_id'), 'field' => 'user_id'),
array('data' => t('mail'), 'field' => 'mail'),
array('data' => t('Updated'), 'field' => 'changed', 'sort' => 'desc'),
array('data' => t('Actions'))
);
//Build the rows.
$options = array();
$query = db_select('mon_module_password', 'mmp')->extend('PagerDefault');
$query->fields('mmp', array('id', 'node_id', 'password', 'user_id', 'changed'));
$query->join('users', 'u', 'u.uid = mmp.user_id');
$query->fields('u', array('mail'));
$query->join('node', 'n', 'n.nid = mmp.node_id');
$query->fields('n', array('title'));
$query->limit(50);
$query->extend('TableSort')->orderByHeader($header);
if(isset($_SESSION['form_values']['mail'])) {
$query->condition('u.mail', '%' . db_like($_SESSION['form_values']['mail']) . '%', 'LIKE');
}
if(isset($_SESSION['form_values']['password'])) {
$query->condition('mmp.password', '%' . db_like($_SESSION['form_values']['password']) . '%', 'LIKE');
}
if(isset($_SESSION['form_values']['node_id'])) {
$query->condition('mmp.node_id', $_SESSION['form_values']['node_id'], '=');
}
$result = $query->execute();
foreach ($result as $row) {
$option = array();
$option[] = array('data' => $row->id);
$option[] = array('data' => $row->node_id);
$option[] = array('data' => l($row->title, 'node/'. $row->node_id.'/edit'));
$option[] = array('data' => $row->password);
$option[] = array('data' => $row->user_id);
$option[] = array('data' => l($row->mail, 'user/'. $row->user_id .'/edit'));
$option[] = array('data' => (!empty($row->changed) ? date('d/m/Y H:i:s', $row->changed) : ''));
$option[] = array('data' => array('#type' => 'link', '#title' => t('edit'), '#href' => "admin/mon_module/$row->id/edit"));
$options[] = $option;
}
//Build the tableselect.
$form['table'] = array(
'#type' => 'tableselect',
'#header' => $header,
'#options' => $options,
'#empty' => t('Aucun enregistrement.'),
'#sticky' => TRUE,
'#attributes' => array(),
);
$form['pager'] = array('#markup' => theme('pager'));
/* Using foreach: */
foreach( $options as $key => $value )
{
$form['table'][$key]['#disabled'] = true;
}
return $form;
}
Plusieurs choses importantes dans cette partie de code :
- j'ai ajouté un
$form['search']
pour avoir une partie en haut de la liste pour filtrer les résultats. Le formulaire qui s'affiche ici est appelé via undrupal_get_form(password_filter_form)
- dans le
$header
, le fait d'ajouter unfield
ajoute un lien pour trier une colonne de la liste. Il faut mettre le nom de la colonne en base de données. On peut également spécifier un tri par défaut en ajoutant unsort
(voir la colonne "Updated"). - dans la requête les conditions sont liées aux filtres
- dans l'affichage des résultats je prépare de suite le lien pour updater un enregistrement.
- quelques infos supplémentaires sur la fonction tableselect
Code pour filtrer les résultats :
/**
* Implements hook_form().
*/
function password_filter_form($form, &$form_state) {
// ajout d'un css pour afficher proprement les filtres
drupal_add_css(drupal_get_path('module', 'mon_module') . '/css/admin.css', array('weight' => CSS_THEME));
// Sets the values that are stored in session as default.
$storage = (isset($_SESSION['form_values']) ? $_SESSION['form_values'] : 0);
$selected_email = isset($storage['mail']) ? $storage['mail'] : NULL;
$selected_password = isset($storage['password']) ? $storage['password'] : NULL;
$selected_node_id = isset($storage['node_id']) ? $storage['node_id'] : NULL;
$downloads = get_all_download_content_type();
$all_download_titles = array();
foreach($downloads as $download){
$all_download_titles[$download->nid] = $download->title;
}
$form['node_id'] = array(
'#title' => 'Par download',
'#type' => 'select',
'#options' => $all_download_titles,
'#default_value' => $selected_node_id,
);
$form['mail'] = array(
'#title' => 'Par email',
'#type' => 'textfield',
'#default_value' => $selected_email,
'#size' => '30',
);
$form['password'] = array(
'#title' => 'Par mot de passe',
'#type' => 'textfield',
'#default_value' => $selected_password,
'#size' => '30',
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Filter'),
);
$form['reset'] = array(
'#type' => 'submit',
'#value' => t('Reset'),
'#weight' => 30,
'#submit' => array('password_reset'),
);
return $form;
}
A ce niveau on obtient la liste suivante :
2. Ajouter un formulaire pour créer ou modifier une entité
Ci-dessus on a ajouté un lien pour éditer un enregistrement, voyons donc comment mettre en place ce formulaire?
Dans le fichier "mon_module.admin.inc", on ajoute le menu d'édition et également d'ajout de l'entité :
$items['admin/mon_module/%/edit'] = array(
'title' => 'Modifier une entité',
'page callback' => 'drupal_get_form',
'page arguments' => array('mon_module_content_type_edit_form', 2),
'access arguments' => array('administrer site configuration'),
'file' => 'mon_module.admin.inc',
);
$items['admin/mon_module/add'] = array(
'title' => 'Ajouter une entité',
'page callback' => 'drupal_get_form',
'page arguments' => array('mon_module_content_type_edit_form'),
'access arguments' => array('administrer site configuration'),
'file' => 'mon_module.admin.inc',
'type' => MENU_LOCAL_ACTION,
);
Puis on crée le formulaire d'édition de l'entité :
/**
* Retourne le formulaire d'édition d'une entité
*/
function mon_module_content_type_edit_form($form, &$form_state, $download_id = null){
$query = db_select('download_password', 'dp');
$query->fields('dp', array('id', 'node_id', 'password', 'user_id', 'changed'));
$query->condition('dp.id', $download_id, '=');
$download_entity = $query->execute()->fetch();
$downloads = get_all_download_content_type();
$all_download_titles = array();
foreach($downloads as $download){
$all_download_titles[$download->nid] = $download->title;
}
$form['download_content_type'] = array(
'#title' => 'Accès sur la publication',
'#type' => 'select',
'#default_value' => '',
'#disabled' => (!empty($download_id) ? true : false),
'#options' => $all_download_titles,
);
$form['download_id'] = array(
'#title' => 'Accès sur la publication',
'#type' => 'hidden',
'#value' => $download_id,
);
$form['download_password'] = array(
'#title' => 'Password',
'#type' => 'textfield',
'#disabled' => (!empty($download_id) ? true : false),
'#default_value' => $download_entity->password,
);
$form['download_mail'] = array(
'#title' => 'Courriel',
'#type' => 'textfield',
'#default_value' => get_mail_by_user_id($download_entity->user_id),
);
$form['edit'] = array(
'#value' => 'Enregistrer',
'#type' => 'submit',
'#name' => 'edit_abonnement',
);
$form['reset'] = array(
'#type' => 'submit',
'#value' => t('Cancel'),
'#weight' => 30,
'#submit' => array('download_reset'),
);
return $form;
}
Le code du bouton reset :
/*
* Bouton annuler sur le formulaire de modification d'un accès
*/
function download_reset() {
drupal_set_message('Modification annulée');
drupal_goto('admin/mon_module/list');
}
Le traitement du formulaire :
/**
* Implements hook_submit
* Récupère et met à jour les droits/abonnement
*/
function mon_module_content_type_edit_form_submit($form, &$form_state){
// update
if(!empty($form_state['values']['download_id'])) {
$user = get_user_id_by_mail($form_state['values']['download_mail']);
if(!empty($user) && $user != 0) {
update_download_files_access_by_id(
$form_state['values']['download_id'],
$user
);
drupal_set_message('L\'enregistrement a bien été modifié');
}
else {
drupal_set_message('Cet utilisateur n\'a pas de compte sur le site, il ne peut pas être associé.', 'error');
}
}
//insert
else {
insert_download_files_access_by_id(
$form_state['values']['download_content_type'],
$form_state['values']['download_password'],
get_user_id_by_mail($form_state['values']['download_mail'])
);
drupal_set_message('Le nouvel accès a bien été créé');
}
drupal_goto('admin/mon_module/list');
}
3. Créer un lien pour supprimer une entité
De la même façon on ajoute un menu au fichier .
$items['admin/mon_module/%/delete'] = array(
'title' => 'Supprimer une entité',
'description' => 'Description',
'page callback' => 'delete_entity',
'page argument' => array(2),
'access arguments' => array('administrer site configuration'),
);
Et on ajoute la fonction de callback pour supprimer un élément :
function delete_entity() {
$id = arg(2);
$num_updated = db_delete('mon_module_password')
->condition('id', $id, '=')
->execute();
drupal_set_message(t('Enregistrement supprimé!'));
drupal_goto("admin/mon_module/list");
}
Et on crée le lien de suppression au même endroit que celui pour la modification ci dessus.
Quelques liens pour continuer sur le sujet avec un autre exemple de CRUD en D7 et le même exercice de CRUD en D8.