Drupal Install Profile

Drupal Install Profile

Probably everybody have come across with ready-to-use site packages on Drupal where after installation you get a ready site with the set of necessary modules, personal theme and so on. There are many such packages, among which Open Atrium, Drupal Commons and others. I’m sure the question appeared: “How was it realized?” or “How can it be done?” The answer to this question is Drupal Install Profile. So how can a personal install profile be created? Generally install profiles are created on the basis of the existed site.

Step 1. Preparation of files.

Create “modules” folder, “contrib” folder in it into which all the modules necessary for work are copied.

“themes” folder is created into which a folder with our themes is put, for example, acquia_prosper, and .tpl.php sets and .js and .css files created in the process of site development. To include several special elements of site into a package, such as views, content type, menu, roles, access rights and others, Features module is used. Created features are put into “features” folder and added to “modules” folder.

Note: At the moment Features module doesn’t transfer taxonomy dictionaries and terms into them, maybe it will be done in the following versions of module, that’s why it should be done manually. It’ll be described further.

We’ll get the following structure:


      • modules
      • contrib
      • features
    • themes

Step 2. Creation of .profile file

This file is the “brain” of our profile; it manages the site installation process.

Note: At this stage of site work function t() doesn’t function, that’s why its equivalent st () is used.

2.1. myprofile.profile is created.


Function myprofile_profile_modules () is formed. In this function the modules are described which should be turned on after installation.

// $Id$

// indicate dictionary taxonomy id

// indicate topic title
define('MYPROFILE_ACQUIA_THEME', 'acquia_prosper');
define('MYPROFILE_FUSION_CORE', 'fusion_core');

 * Returns array of modules which will be turned on after profile installation
function myprofile_profile_modules() {
  $modules = array(
    // Default Drupal modules.
    'color', 'comment', 'dblog', 'help', 'menu', 'path', 'taxonomy',
    'admin', 'admin_menu',
    'content', 'text', 'ctools', 'content_permissions', 'fieldgroup', 'filefield',
    'optionwidgets', 'nodereference', 'userreference',
    'imageapi', 'imageapi_gd', 'imagecache', 'imagecache_ui', 'imagecache_customactions',
    'views', 'views_bulk_operations', 'viewscarousel', 'views_export', 'views_or', 'views_slideshow',
    'nodewords', 'nodewords_basic', 'nodewords_extra', 'nodewords_verification_tags',
    'imce', 'wysiwyg', 'jquery_ui', 'jquery_update', 'dialog','vertical_tabs', 'imce_wysiwyg',
    'skinr', 'skinr_ui',
    'better_formats', 'globalredirect', 'no_anon', 'pathauto',
    'url_alter', 'subpath_alias', 'token_actions', 'transliteration', 'vertical_tabs',
    'ca', 'uc_order', 'uc_store', 'uc_product', 'uc_cart',
    'uc_payment', 'uc_reports', 'uc_shipping', 'uc_product_power_tools', 'uc_stock',
    'xmlsitemap', 'xmlsitemap_engines', 'xmlsitemap_menu', 'xmlsitemap_node'

  return $modules;

Note: Modules which “depend on” other ones should be indicated after those that they depend on. There are also problems when url_alter module is turned on. The decision can be found here.

2.3. _profile_details().

Profile description which will be shown on profile installation screen.

/** @return
 * array with keys "name" and "description", describing the given profile,
 * and additional "language", to redefine language for a profile
function myprofile_profile_details() {
  $description = st('Select this profile to install the My custom profile.');
  return array(
    'name' => 'My profile',
    'description' => $description,

Note: Modules which “depend on” other ones should be indicated after those that they depend on. There are also problems when url_alter module is turned on. The decision can be found here.

2.4. _profile_task_list()

List of tasks that will be done during profile installation.

function myprofile_profile_task_list() {
  $tasks = array();
  $tasks['configure-myprofile'] = st('Configure My profile');
  $tasks['install-myprofile'] = st('Install My profile');
  return $tasks;

2.5. _profile_tasks(&$task, $url)

This function is responsible for this stage of profile installation.

 * .
 */It executes the final tasks of profile installation.
function myprofile_profile_tasks(&$task, $url) {
  // skipping the standard installation stage.
  if ($task == 'profile') {
    $task = 'install-myprofile';  
  // It returns features form
  if ($task == 'configure-myprofile') {
    $output = drupal_get_form('myprofile_features_form', $url);
  // installation batch process
  if ($task == 'install-myprofile') {
    $operations = array();
    // pre-installation operations
    $operations[] = array('myprofile_config_taxonomy', array());
 // creating taxonomy dictionary

    // “features” installation
    $features = variable_get('myprofile_selected_features', array());
    foreach ($features as $feature) {
      $operations[] = array('features_install_modules', array(array($feature)));

    // post-installation operations
    $operations[] = array('myprofile_config_theme', array()); // 
turning on the personal theme
    $operations['finished'] = 'myprofile_configure_batch_finished';
    // building batch process
    $batch = array(
      'operations' => $operations,
      'title' => st('Configuring My profile'),
      'error_message' => st('An error occurred. Please try reinstalling again.'),
      'finished' => 'myprofile_cleanup',
    // building batch process
    variable_set('install_task', 'install-myprofile-batch');
    batch_process($url, $url);
  // It shows batch execution page
  if ($task == 'install-myprofile-batch') {
    include_once 'includes/';
    $output = _batch_page();
  return $output;

2.6. _features_form()

“Choose from available features” form to transfer their functional on the site.

function myprofile_features_form($form_state, $url) {
  $form = array();
  drupal_set_title(st('Choose from available features'));
  // Ancillary message
  $form['message'] = array(
    '#type' => 'item',
    '#value' => st('The selected features will be enabled after the installation has completed. At any time, you can turn the available features on or off.'),

  $form['content'] = array(
    '#type' => 'checkbox',
    '#title' => st('Content types'),
    '#default_value' => 1,
    '#description' => st('Some test content types'),
  $form['menu_links'] = array(
    '#type' => 'checkbox',
    '#title' => st('Menu'),
    '#default_value' => 1,
    '#description' => st('Some test menu'),
  $form['views_default'] = array(
    '#type' => 'checkbox',
    '#title' => st('View'),
    '#default_value' => 1,
    '#description' => st('Some test view'),

  // Returns to installation without its abort.
  $form['url'] = array(
    '#type' => 'value',
    '#value' => $url,
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => st('Continue'),
  return $form;

2.7. _features_form_submit()

This function forms the array of chosen features.

function myprofile_features_form_submit(&$form, &$form_state) {
  // chosen features batch
  $features = array();
  foreach ($form_state['values'] as $key => $value) {
    $features[] = $key;
  // forming temporary variable with chosen features.
  variable_set('myprofile_selected_features', $features);
  // initiating the next step of installation
  variable_set('install_task', 'install-myprofile');
  // returning to the installation page


Creating taxonomy dictionary.

function myprofile_config_taxonomy() {  
   $vocab = array(
    'name' => st('Test'),
    'description' => st('Test vocabulary'),
    'multiple' => '1',
    'required' => '1',
    'hierarchy' => '1',
    'relations' => '1',
    'tags' => '0',
    'module' => 'taxonomy',
  db_query("UPDATE {vocabulary} SET vid = %d WHERE name = '%s", MYPROFILE_NEWS_VOCAB_ID, st('Test'));


Turning on the personal theme, i.e. it will become active after installation.

function myprofile_config_theme() {
  // turning off garland theme
  db_query("UPDATE {system} SET status = 0 WHERE type = 'theme' and name = '%s'", 'garland');
  // turning on fusion and acquia_prosper themes
  db_query("UPDATE {system} SET status = 1 WHERE type = 'theme' and name = '%s
                  ",  MYPROFILE_ACQUIA_THEME);
  db_query("UPDATE {system} SET status = 1 WHERE type = 'theme' and name = '%s
                  ", MYPROFILE_FUSION_CORE);

  // setting acquia_prosper theme by default
  variable_set('theme_default', MYPROFILE_ACQUIA_THEME);
  // rebuilding registry


Cleaning up after we are done :) .

function myprofile_cleanup() {
  // rebuilding types of content
  // filtering cache
  $core = array('cache', 'cache_block', 'cache_filter', 'cache_page');
  $cache_tables = array_merge(module_invoke_all('flush_caches'), $core);
  foreach ($cache_tables as $table) {
    cache_clear_all('*', $table, TRUE);
  // clearing JC and CSS caches
  // features should be returned
  $revert = array(
    'myprofile_features' => array('content', 'menu_links', 'views_default')
  // completing installation
  variable_set('install_task', 'profile-finished');

Created myprofile.profile should be put into "myprofile" folder.

The final structure of files is:


    • modules
    • contrib
    • features
  • themes
  • myprofile.profile

The last thing that is needed is to transfer a folder with our profile "myprofile" into Drupal distributive using the way drupal-6.х -> profiles.

Note: This example was made on the basis of Drupal Commons, it can serve as an example of install profile realization.

Conclusion. In order to create our install profile, we need to create a “package” with necessary modules, features and theme and also to create .profile file.

6 votes, Rating: 5

Read also


Cron.php script is used in Drupal for content indexation, sending e-mails to subscribers, gathering rss-feeds and so on – modules can give task themselves to be done according to schedule.


While developing a real estate site for one of our clients we tried to import...


It’s a very helpful module, which allows inserting FileField right into the text editor. For example, in the process of writing this text an Insert button was pushed and the following image...


This kind of mistake can be seen on servers with nginx as frontend and Apache as backend. It’s usually considered to be a nginx problem which is tried to be strenuously solved. Quite often it’s...