Distribution from .info file
| Project: | Install Profile API |
| Version: | 6.x-2.x-dev |
| Component: | Other |
| Category: | feature request |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | won't fix |
Jump to:
So first of all, this module is great, thanks for the amazing combined effort on it.
I have an idea for greatly simplifying creation of new install profiles or "distributions" as I'm going to refer to them. Maybe this has already been tossed around somewhere, but I'm what I propose is creating distribution info files in the PHP ini format, that declares input formats, roles, variables, etc. and install_profile_api has a function that just loads in that info file and fires off the appropriate functions to do the dirty work.
If we model it after themes, we can have a sub-distribution that has a "base" distribution. All the info is parsed from the base .info file, and the sub-distro is merged with that.
The nice thing about this too, is that it would be real easy to get to a point where you can actually diff an existing site from the initial distribution file and export a new distribution file from that diff. Imagine how quickly you could create new install profiles, or "distributions" using this method? Or how quickly you could modify an existing one?
Thoughts? I really think this would eventually be core-worthy, having a base drupal distribution that you could base your distro off of, or start clean with your own distro. I've attached a short sample .info file so you can see what I mean.
| Attachment | Size |
|---|---|
| basic.info | 1.03 KB |

#1
some examples of how a distribution info file would be parsed:
<?php
if ($distribution['roles']) {
foreach($distribution['roles'] as $rid => $name) {
if ($rid != 0 && $rid != 1) {
db_query("DELETE FROM {role} WHERE rid = %d");
if ($name) {
db_query("INSERT INTO {role} (rid, name) VALUES (%d, '%s')", $rid, $name);
}
}
else {
db_query("INSERT INTO {role} (name) VALUES ('%s')", $name);
}
}
}
if ($distribution['users']) {
foreach($distribution['users'] as $array) {
if ($array['uid'] && ($account = user_load($array['uid']))) {
user_save($account, $array);
}
else {
// For some reason db_last_insert_id() doesn't get the uid of the newly created user,
// so we need to separate out roles first, create the account, then save again to
// properly assign roles to this user.
$roles = $array['roles'];
unset($array['roles']);
user_save(new stdClass(), $array);
if ($roles && $array['name']) {
$account = user_load(array('name' => $array['name']));
user_save($account, array('roles' => $roles));
}
}
}
}
if ($key = $distribution['theme']) {
system_theme_data();
variable_set('theme_default', $key);
list_themes(TRUE);
system_initialize_theme_blocks($key);
db_query("UPDATE {system} SET status = 1 WHERE type = 'theme' and name = '%s'", $key);
list_themes(TRUE);
menu_rebuild();
drupal_rebuild_theme_registry();
$settings = theme_get_settings($key);
$var = str_replace('/', '_', 'theme_'. $key .'_settings');
variable_set($var, $settings);
}
if ($distribution['input-formats']) {
foreach($distribution['input-formats'] as $name => $data) {
require_once('./profiles/includes/install_profile_api/core/filter.inc');
$format_id = install_add_format($name);
if ($data['default']) {
variable_set('filter_default_format', $format_id);
}
if ($data['allowed-html']) {
variable_set('allowed_html_'. $format_id, $data['allowed-html']);
}
if ($data['roles']) {
install_format_set_roles($data['roles'], $format_id);
}
if ($data['filters']) {
db_query("DELETE FROM {filters} WHERE format = %d", $format_id);
foreach($data['filters'] as $module => $deltas) {
if (is_array($deltas)) {
foreach($deltas as $delta => $weight) {
db_query("INSERT INTO {filters} (format, module, delta, weight) VALUES (%d, '%s', %d, %d)", $format_id, $module, $delta, $weight);
}
}
}
}
}
}
if ($distribution['variables']) {
foreach($distribution['variables'] as $key => $value) {
variable_set($key, $value);
}
}
if ($distribution['permissions']) {
require_once('./profiles/includes/install_profile_api/core/user.inc');
foreach ($distribution['permissions'] as $rid => $perms) {
install_add_permissions($rid, $perms);
}
}
if ($distribution['node-types']) {
require_once('./profiles/includes/install_profile_api/core/node.inc');
foreach($distribution['node-types'] as $properties) {
$content_type = $properties['type'];
$content_name = $properties['name'];
install_create_content_type($content_type, $content_name, $properties);
}
}
if ($distribution['nodes']) {
require_once('./profiles/includes/install_profile_api/core/node.inc');
foreach($distribution['nodes'] as $nid => $properties) {
if (is_numeric($nid)) {
$properties['nid'] = $nid;
}
$title = $properties['title'];
$body = $properties['body'];
install_create_node($title, $body, $properties);
}
}
if ($distribution['menus']) {
require_once('./profiles/includes/install_profile_api/core/menu.inc');
foreach($distribution['menus'] as $menu) {
install_menu_create_menu($menu['title'], $menu['name'], $menu['description']);
}
}
if ($distribution['menu-items']) {
menu_rebuild();
require_once('./profiles/includes/install_profile_api/core/menu.inc');
foreach($distribution['menu-items'] as $item) {
// We need a link_path to do anything.
if ($item['link_path']) {
if ($items = install_menu_get_items($item['link_path'])) {
foreach($items as $menu_item) {
if ($menu_item['mlid']) {
$item['mlid'] = $menu_item['mlid'];
menu_link_save($item);
}
}
}
elseif($item['link_title']) {
install_menu_create_menu_item(
$item['link_path'],
$item['link_title'],
$item['description'],
$item['menu_name'],
$item['plid'],
$item['weight'],
$item['module'],
$item['hidden'],
$item['has_children'],
$item['expanded'],
$item['customized'],
$item['updated']
);
}
}
}
}
?>
#2
So, of course I was really hoping I was the first person to think of this, in hopes of winning a pony at the next drupalcon, but after talking to adrian he pointed me to this: #509404: Fix some conceptual problems with install profiles and make them actually usable
I still think this would be a good thing to add to install_profile_api for D6
#3
Nobody says you can't add junk to install profiles. My ultimate goal for http://drupal.org/project/drush_make is to be able to be some of that junk that can be in .info files. I like this idea a lot (for D7 especially). You can have various modules register functions for the different items in the .info files:
<?phpfunction install_profile_api_info_keys() {
return array(
'roles' => array(
'module' => 'user',
'function' => 'install_profile_api_user_role_create'
),
);
}
?>
install_profile_api_user_role_create then gets passed the array from the info file and as an optional second argument gets passed the key (such as WYSIWYG for the input-formats)
#4
I'm glad you like this! I had lost hope after talking to Adrian about it on IRC. Your idea sounds like a good one, although I think it might be more flexible if the module itself (in this case install_profile_api) registered which info keys it has functions for, and the location of the function, and then your _info_keys() function (inside the install profile) would just specify the module it wants to process the info values. Just throwing this out real quick, so this is messy and not very good, but hopefully you'll get the idea of what I'm talking about:
<?phpfunction myinstallprofile_info_keys() {
return array(
'roles' => array(
'package' => 'user',
'op' => 'create',
'module' => 'install_profile_api',
),
);
}
?>
<?php
/**
* Implementation of hook_info_keys_registry().
*/
function install_profile_api_info_keys_registry() {
$items = array();
$items['user']['roles']['create'] = array(
'function' => 'install_profile_api_user_role_create',
'arguments' => array('roles' => NULL),
'file' => 'user.inc',
'path' => drupal_get_path('module', 'install_profile_api') .'/core',
);
return $items;
}
?>
#5