Plus Drupal mûrit plus on cherche à industrialiser la production de sites. Une des solutions que l'on propose maintenant courament face à cette demande est l'utilisation de profils d'installation. Oui, mais comment fait-on pour les créer ?
C'est très simple, commençons par reprendre l'arborescence de Drupal. On passe tellement de temps à travailler dans /sites/all/modules que l'on en oublie parfois qu'il existe d'autres répertoires où l'on peut travailler (mais jamais dans /modules ! Pensez aux chatons).
A la racine du dossier de Drupal il existe un répertoire /profiles qui contient à minima un dossier default. C'est le profil qui est utilisé à chaque fois que vous faites une installation de base de Drupal 6. Si vous avez la curiosité de regarder le contenu de ce dossier vous allez vous rendre compte qu'il n'est pas très volumineux car il ne contient que le fichier default.profile.
Organisation d'un profil d'installation #
Le profil d'installation est donc composé comme suit :
- /profiles/monprofil/monprofil.profile
- /profiles/monprofil/modules
- /profiles/monprofil/themes
- /profiles/monprofil/translations
Seul monprofil.profile est obligatoire, les dossiers supplémentaires modules, themes et translations sont respectivement présents pour permettre l'utilisation de modules supplémentaires, de thèmes additionnels ou de langue complémentaires. L'intérêt du profil d'installation est qu'il est distribuable, c'est pour cette raison que si vous utilisez des modules autres que ceux du core vous devez les placer au sein d'un répertoire modules. (Si les modules sont présents dans /sites/*/modules le code fonctionnera mais en terme le logique il est recommandé de placer ces modules dans /profiles/monprofil/modules). Il en va de même pour les thèmes.
Et d'un point de vue code ? #
Dans la plus petite version possible d'un profil d'installation (identique à default.profile) il faut à minima déclarer ces fonctions :
-
- example_profile_modules() // retourne un tableau des modules à installer
-
- example_profile_details() // retourne un tableau avec les détails du profil avec les deux clés name et description)
Optionnelles
-
- example_profile_task_list() // Etapes intermédiaires du profil
-
- example_profile_tasks(&$task, $url) // Execute les dernières taches du profil d'installation
example_profile_modules() #
Cette fonction est généralement utilisée pour activer les modules de core dont vous allez avoir besoin. Pour activer les modules contribs, on a l'habitude de créer une étape intermédiaire compte tenu du fait qu'ils dépendent très souvent des modules de core et qu'ils sont nombreux (on utilisera l'API de batch afin de ne pas faire tomber le serveur).
function MONPROFIL_profile_modules() {
return array('color', 'comment', 'help', 'menu', 'taxonomy', 'dblog');
}
example_profile_details() #
Difficile de sélectioner votre profil d'installation si cette fonction n'est pas présente car elle indique son petit nom et une description.
function MONPROFIL_profile_details() {
return array(
'name' => st('Custom installation profile'),
'description' => st('This is my first installation profile')
);
}
Note : Au sein d'un profil d'installation il faut utiliser la fonction st() au lieu de t() pour internationaliser vos chaines de caractères. Les fichiers .po doivent se trouver au sein du dossier /profiles/monprofil/translations.
example_profile_task_list() #
Si vous créez des étapes intermédiaires dans votre profil il est intéressant d'indiquer à votre utilisateur sa progression. Ce sont les états que l'on retrouve à gauche au cours de l'installation.
function openatrium_profile_task_list() {
return array(
'intranet-modules-batch' => st('Install intranet modules'),
'intranet-configure-batch' => st('Configure intranet'),
);
}
example_profile_tasks(&$task, $url) #
C'est la fonction la plus utile du profil d'installation car c'est dans cette dernière que l'on va faire la configuration des modules, la création de types de contenus, la création de nodes, d'utilisateurs bref c'est là que l'on fait réellement ce qui nous intéresse. Voici une copie de l'implémentation de cette fonction dans le profil d'installation d'Open Atrium, je reviendrai ci-dessous en détails sur les parties importantes.
function openatrium_profile_tasks(&$task, $url) {
global $profile, $install_locale;
// Just in case some of the future tasks adds some output
$output = '';
// Download and install translation if needed
if ($task == 'profile') {
// Rebuild the language list.
// When running through the CLI, the static language list will be empty
// unless we repopulate it from the ,newly available, database.
language_list('name', TRUE);
// If we reach here, means no language install, move on to the next task
$task = 'intranet-modules';
}
// We are running a batch task for this profile so basically do nothing and return page
if (in_array($task, array('intranet-modules-batch', 'intranet-translation-batch', 'intranet-configure-batch'))) {
include_once 'includes/batch.inc';
$output = _batch_page();
}
// Run additional configuration tasks
// @todo Review all the cache/rebuild options at the end, some of them may not be needed
// @todo Review for localization, the time zone cannot be set that way either
if ($task == 'intranet-configure') {
$batch['title'] = st('Configuring @drupal', array('@drupal' => drupal_install_profile_name()));
$batch['operations'][] = array('_openatrium_intranet_configure', array());
$batch['operations'][] = array('_openatrium_intranet_configure_check', array());
$batch['finished'] = '_openatrium_intranet_configure_finished';
variable_set('install_task', 'intranet-configure-batch');
batch_set($batch);
batch_process($url, $url);
// Jut for cli installs. We'll never reach here on interactive installs.
return;
}
return $output;
}
Premier point important, le déroulé des étapes :
- profile
- intranet-modules
- intranet-modules-batch
- intranet-configure
- intranet-configure-batch
- profile-finished
La première étape d'un profil d'installation à partir de laquelle l'installeur vous donne la main est toujours "profile" et vous devez avoir comme dernière étape "profile-finished" pour rendre la main à l'installeur. Vous ne pouvez donc pas intervenir sur ce qui se passe avant et après !
Votre profil d'installation va donc passer autant de fois que nécessaire dans la fonction hook_profile_tasks(), les seuls conditions nécessaires pour que la répétition cesse sont :
- Vous donnez la valeur "profile-finished" à la variable $task
- Vous ne changez pas la valeur de la variable $task
Pour passer d'une étape à une autre vous devez changer la valeur de $task. Si vous affichez un formulaire ou exécutez une action en batch vous allez devoir utiliser variable_set('install_task', 'valeur-tache'); pour stocker l'étape dans laquelle vous êtes.
On voit également dans le profil d'installation d'Open Atrium comment gérer une opération en batch, c'est une action en deux étapes, la première consiste à créer le batch, définir la(es) opération(s), la fonction à exécuter à la fin du batch et toutes les variables propres aux batchs (cf Batch API pour plus d'informations) et la seconde lance le traitement du batch _batch_page(); . Difficile à inventer si on ne l'a jamais vu ;).
Je vais terminer avec un snippet pour afficher un formulaire comme étape du profil d'installation, c'est là aussi une opération particulière car il faut faire deux choses, il faut d'abord bloquer la redirection du formulaire avec $form['#redirect'] = FALSE; et ensuite préciser vers quelle url soumettre le formulaire grâce à $form['#action'] = $url; (en pensant à passer $url comme paramètre supplémentaire à votre formulaire) pour que votre formulaire permette la poursuite de l'exécution du profil.
// Extract of the hook_profile_tasks
// Define extra actions if the development environment is enabled
if ($task == 'development-environment') {
$output = drupal_get_form('custom_profile_dev_form', $url);
if (!variable_get('developement_environment_checked', false)) {
drupal_set_title(st('Select the environment you want to setup'));
return $output;
}
else {
$setup_dev_env = variable_get('setup_dev_env', FALSE);
variable_del('developement_environment_checked');
variable_del('setup_dev_env');
// Setup the environment dev if checked
if ($setup_dev_env) {
$task = 'setup-dev-env';
}
else {
$task = 'install-extra-modules';
}
}
}
// --
// Custom form
function custom_profile_dev_form(&$form_state, $url) {
$form = array();
$form['#redirect'] = false;
$form['#action'] = $url;
$form['development_environment'] = array(
'#title' => st('Enable development environment'),
'#type' => 'radios',
'#options' => array('No', 'Yes'),
'#default_value' => 1,
'#required' => TRUE,
'#description' => st('This will install modules like Devel and create dummy content.'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => st('Confirm'),
);
return $form;
}
Voilà qui termine un assez long article sur les profils d'installation, n'hésitez pas à partager vos astuces et à poser vos questions dans les commentaires.