使用安装和分发加速您的 Drupal 开发
当您开始一个新的 Drupal 项目时,您是否发现自己重复相同的步骤?您是否总是下载并启用相同的模块,并且每次都进行相同的配置更改?随着我们在 Nomensa 开始做越来越多的 Drupal 项目,我注意到我们正在完全这样做,所以我开始研究简化我们初始项目设置流程的方法。我的解决方案是创建我自己的自定义安装配置文件,为我提供一个启动每个项目的模板,本文概述了我创建它的步骤。本文中概述的代码已提交到 GitHub,地址为 https://github.com/opdavies/linuxjournal_demo,您可以根据需要下载和重复使用。
什么是安装配置文件?安装配置文件是模块、主题和预定义配置的组合。我经常使用的安装配置文件的一个很好的例子是 Commerce Kickstart (http://drupal.org/project/commerce_kickstart)。它提供了 Drupal 7 的一个版本,以及 Drupal Commerce 模块套件,这些模块已预先配置为具有正确的内容类型、规则、视图等等。一旦安装配置文件作为项目上传到 drupal.org,它就会与 Drupal 核心捆绑在一起,可以作为打包下载使用,并被称为发行版。有关现有发行版的列表,请参阅 http://drupal.org/project/distributions。

图 1. Commerce Kickstart 项目页面
如何安装现有的安装配置文件有两种不同的方法可以下载现有的 Drupal 安装配置文件。第一种(也是最简单的方法)是从 drupal.org 下载它作为发行版。为此,请转到安装配置文件的项目页面(例如,http://drupal.org/project/commerce_kickstart),滚动到页面底部,并以下载模块或主题的相同方式下载一个版本。生成的文件将命名为类似 commerce_kickstart-7.x-1.10-core.tar.gz,并且此文件将包含 Drupal 核心和 Commerce Kickstart 安装配置文件。另一种选择是下载 Drupal 核心的新副本,然后单独下载安装配置文件,可以使用类似 drush dl commerce_kickstart
的 drush 命令,或者直接从其 Git 存储库克隆它,然后将其放置在 Drupal 的 profiles 目录中。
现在,当您去安装 Drupal 时,有一个额外的选项可以使用 Commerce Kickstart 安装配置文件。选择适当的配置文件,单击“保存并继续”按钮,并像往常一样继续完成安装过程。

图 2. 带有 Commerce Kickstart 的安装屏幕
如何开始创建您自己的安装配置文件在您的 Drupal 目录之外,创建一个新目录来保存您的安装配置文件的文件。我的目录名为 linuxjournal_profile,尽管配置文件的名称将只是 linuxjournal。我在目录名称的末尾附加了 _profile。稍后,将有几个不同名称相似的目录,因此这有助于提供一些清晰度。请务必事先考虑名称,并确保它不与任何潜在的模块或主题冲突。
我需要创建的第一个文件是 linuxjournal.info 文件,它与模块和主题的 .info 文件相同,定义了配置文件的名称和描述,以及它兼容的 Drupal 核心版本。我还将使其依赖于核心 dblog 和 block 模块,以便在安装配置文件时自动启用这些模块
name = Linux Journal
description = A demonstration installation profile for my LJ article.
core = 7.x
dependencies[] = dblog
dependencies[] = block
此配置文件对 Drupal 可见所需的唯一其他必需文件是 .profile 文件——在本例中为 linuxjournal.profile。在此文件中,我可以放置任何自定义 PHP 函数或 Drupal hooks 的实现,这些函数或实现在安装过程中生效。现在,我只想添加一个 PHP 开始标签,并将文件的其余部分留空。为了确认到目前为止一切正常,我可以下载 Drupal 核心的新副本,将 linuxjournal_profile 复制到 profiles 目录中,将其重命名为 linuxjournal,使其与配置文件的名称相同,并在 Web 浏览器中加载该站点。

图 3. 带有 Linux Journal 安装配置文件的安装屏幕
到目前为止,一切顺利。在安装页面上,除了看到默认的 Standard 和 Minimal 配置文件外,我还可以看到我的 Linux Journal 配置文件。我可以选择此配置文件并像往常一样继续安装过程,以确认它正在工作,尽管因为我尚未在 linuxjournal.profile 中输入任何内容,所以不会发生任何特殊情况。
添加 .install 文件与编写模块相同,我可以创建一个 .install 文件,其中包含在安装、更新或卸载配置文件时运行的函数。我将利用 minimal 安装配置文件中的 hook_install() 函数作为我的配置文件的一部分,而不是重新声明其内容并复制代码。在我自己的 hook_install() 实现中,我可以包含 minimal 配置文件的 .install 文件,然后运行其 minimal_install() 函数
<?php
/**
* @file
* Install, update and uninstall functions
* for the Linux Journal installation profile.
*/
/**
* Implements hook_install().
*
* Run the hook_install() function from the minimal
* profile as part of this profile.
*/
function linuxjournal_install() {
// Utilize the hook_install() implementation from
// the minimal profile.
include_once DRUPAL_ROOT . '/profiles/minimal/minimal.install';
minimal_install();
}
添加模块
我现在要创建另一个名为 linuxjournal.make 的文件。此文件包含配置文件中使用的所有项目(模块和主题)和库的列表。我的公司专门构建可访问的网站,我在每个站点上都使用许多贡献模块来帮助我做到这一点。还有一些重要的贡献模块,例如 Administration Menu (http://drupal.org/project/admin_menu) 和 Pathauto (http://drupal.org/project/pathauto),以及我在每个站点上使用的一些自定义模块和功能。所有这些都将列在 linuxjournal.make 文件中。
在 linuxjournal.make 的最顶部,我需要添加以下两行来定义 API 版本以及我正在使用的 Drupal 核心版本
api = 2
core = 7.x
这是将项目(在本例中为 Administration Menu 模块)添加到配置文件中的语法。就我个人而言,我喜欢从其 Git 存储库下载项目,尽管它们也可以使用 wget 从 drupal.org 下载。值得注意的是,下载 URL 不必是 drupal.org 上的 URL。您可以从其他来源下载项目,例如 GitHub 或 BitBucket,或任何其他来源,包括来自本地文件目录
projects[admin_menu][type] = module
projects[admin_menu][subdir] = contrib
projects[admin_menu][version] = 3.0-rc3
projects[admin_menu][download][type] = git
projects[admin_menu][download][url] =
↪http://git.drupal.org/project/admin_menu.git
projects[admin_menu][download][branch] = 7.x-3.x
默认情况下,所有指定的模块都将位于 profiles/linuxjournal/modules 目录中;但是,我更喜欢将贡献模块存储在名为 contrib 的子目录中,因此使用 subdir 值。我还指定了要使用的模块版本以及要使用的 Git 存储库中的分支。如果我没有指定版本号,则将使用指定分支的最新提交。
为了使 Administration Menu 模块在安装配置文件后默认启用,我可以将其声明为依赖项,方法是将以下行添加到 linuxjournal.info 中,就像我之前对 dblog 和 block 模块所做的那样
dependencies[] = admin_menu
如果我使用这些更改更新我的 Drupal 版本并尝试按照安装过程进行操作,我将收到一个错误,因为我使配置文件依赖于 Administration Menu 模块,但是此模块尚未为此 Drupal 实例下载。下一步是创建一个发行版,其中包含 linuxjournal 安装配置文件以及 linuxjournal.make 中定义的所有项目。

图 4. 安装时的错误
创建发行版要创建发行版,我需要做的第一件事是创建一个名为 distro.make 的新文件,该文件将用于编译包含 linuxjournal 配置文件的 Drupal 实例。与 linuxjournal.make 一样,我需要从声明 API 版本和 Drupal 核心版本开始。我还需要将 Drupal 核心声明为一个项目,并包含 linuxjournal 配置文件
api = 2
core = 7.x
projects[drupal][type] = core
projects[drupal][version] = "7"
; Add the Linux Journal profile to the full distribution build.
projects[linuxjournal][type] = profile
projects[linuxjournal][download][type] = git
projects[linuxjournal][download][url] =
↪https://github.com/opdavies/linuxjournal_demo.git
同样,我正在使用 Git 下载安装配置文件,并为发行版提供 GitHub 上存储库的 URL。保存 distro.make 后,我现在可以使用以下 Drush 命令编译 Drupal
drush make distro.make directory
最后一个参数是您希望将 Drupal 编译到的目录的名称。如果未指定,将使用您当前所在的目录,我不建议这样做。我希望将结果目录放置在与我的 linuxjournal_profile 目录相同的级别,因此我需要在指定目录名称之前向上移动一个级别,目录名称将为 linuxjournal_demo
drush make distro.make ../linuxjournal_demo
此命令将下载最新版本的 Drupal 7 核心,以及 linuxjournal.profile 中定义的所有项目,到 linuxjournal_demo 目录中。一旦编译完成所有内容,在 profiles/linuxjournal 目录中,将有一个名为 modules/contrib 的新目录,其中包含 admin_menu 模块。下载所有依赖项后,我现在可以再次转到 install.php 并完成安装过程,而不会出现任何错误。
将主题添加到安装配置文件中我可以通过在 linuxjournal.make 中声明主题来将其添加到我的配置文件中,就像我可以对模块一样。由于我将 Omega 用作我的大多数主题的基础主题,因此我将其包含在我的配置文件中,以便自动下载
; Themes =========================================================
projects[omega][type] = theme
projects[omega][version] = 3.1
projects[omega][download][type] = git
projects[omega][download][url] =
↪http://git.drupal.org/project/omega.git
projects[omega][download][branch] = 7.x-3.x
目前,我将手动创建子主题,因此我不会在此处更改默认主题。
自定义站点配置表单在完成安装过程时,我通常会对站点配置表单进行一些更改——即设置默认站点名称并添加默认国家/地区。我可以通过在 linuxjournal.profile 中添加 hook_form_FORM_ID_alter() 的实现来自动化这些更改,因为在此文件中定义的任何函数都将在安装过程中生效。我知道表单的 ID 是 install_configure_form,并且我要创建的函数的名称将是 linuxjournal_form_install_configure_form_alter()
/**
* Implements hook_form_alter().
*
* Allows the profile to alter the site configuration form.
*/
function linuxjournal_form_install_configure_form_alter(&$form,
↪$form_state) {
// Set a default site name.
$form['site_information']['site_name']['#default_value'] =
↪t('Linux Journal Demo');
}
由于表单对象是通过引用传递到函数中的,因此我可以使用此函数在对象中添加或覆盖信息。在这里,我为站点名称字段设置一个默认值,下次我按照安装过程进行操作时,该值将预先填充在站点配置表单上。我可以通过将任何其他值添加到此函数中来添加和覆盖表单上的任何其他值
/**
* Implements hook_form_alter().
*
* Allows the profile to alter the site configuration form.
*/
function linuxjournal_form_install_configure_form_alter(&$form,
↪$form_state) {
// Set a default site name and email address.
$form['site_information']['site_name']['#default_value']
↪= t('Linux Journal Demo');
$form['site_information']['site_mail']['#default_value']
↪= 'linuxjournal@oliverdavies.co.uk';
// Set a default username and email address.
$form['admin_account']['account']['name']['#default_value']
↪= 'Oliver Davies';
$form['admin_account']['account']['mail']['#default_value']
↪= 'linuxjournal@oliverdavies.co.uk';
// Set a default country and timezone.
$form['server_settings']['site_default_country']['#default_value']
↪= 'GB';
$form['server_settings']['date_default_timezone']['#default_value']
↪= 'Europe/London';
// Disable the 'receive email notifications' check box.
$form['update_notifications']['update_status_module']
↪['#default_value'][1] = 0;
}
现在,除了添加默认站点名称外,我还添加了默认站点电子邮件地址、第一个用户帐户的默认用户名和电子邮件地址、添加了默认时区和国家/地区,并禁用了在新更新可用时接收电子邮件警报的选项。出于安全原因,我不想在此文件中定义我的密码,并将继续直接在表单上输入密码。我使用的是 #default_value 而不是 #value,因此如果我需要为此站点这样做,我可以在表单上编辑这些预定义的值。如果我使用 #value,我将无法这样做。

图 5. 站点配置表单
设置管理主题基本上,我现在拥有的是 minimal 安装配置文件的副本,其中包含一些额外的模块和主题。接下来我要做的第一件事是将 Seven 主题用于站点的管理页面,就像我使用 standard 安装配置文件一样。为此,我首先需要启用 Seven,然后设置一些变量以将其设置为管理主题。我可以参考 standard 安装配置文件的 .install 文件来了解如何执行此操作。为此,我将以下代码添加到 linuxjournal.install 中的 linuxjournal_install() 函数中
// Enable the administration theme.
$admin_theme = 'seven';
db_update('system')
->fields(array('status' => 1))
->condition('type', 'theme')
->condition('name', $admin_theme)
->execute();
variable_set('admin_theme', $admin_theme);
variable_set('node_admin_theme', '1');
创建内容类型
standard 安装配置文件还创建了两种默认内容类型:基本页面和文章。我将重用大部分代码来为我的配置文件创建基本页面内容类型
// Add a 'Basic page' content type.
$types = array(
array(
'type' => 'page',
'name' => st('Basic page'),
'base' => 'node_content',
'description' => st("Use <em>basic pages</em> for
↪your static content, such as an 'About us' page."),
'custom' => 1,
'modified' => 1,
'locked' => 0,
);
);
foreach ($types as $type) {
$type = node_type_set_defaults($type);
node_type_save($type);
node_add_body_field($type);
}
// Default 'Basic page' to not be promoted and don't
// display author information.
variable_set('node_options_page', array('status'));
variable_set('node_submitted_page', FALSE);
要创建其他内容类型,我可以继续将新项目添加到 $types 数组中,它们将在 foreach() 循环中处理。
添加文本格式和 WYSIWYG 编辑器当您使用 standard 安装配置文件时,会创建几种不同的文本格式。目前,我只有纯文本和 PHP 代码(因为 PHP 模块现在也是我的配置文件的依赖项)。我还想要其他文本格式,因此我将从 standard.install 文件中复制该代码段并粘贴到 linuxjournal_install() 函数中
// Add text formats.
$text_formats['filtered_html'] = array(
'format' => 'filtered_html',
'name' => 'Filtered HTML',
'weight' => 0,
'filters' => array(
// URL filter.
'filter_url' => array(
'weight' => 0,
'status' => 1,
),
// HTML filter.
'filter_html' => array(
'weight' => 1,
'status' => 1,
),
// Line break filter.
'filter_autop' => array(
'weight' => 2,
'status' => 1,
),
// HTML corrector filter.
'filter_htmlcorrector' => array(
'weight' => 10,
'status' => 1,
),
),
);
$text_formats['full_html'] = array(
'format' => 'full_html',
'name' => 'Full HTML',
'weight' => 1,
'filters' => array(
// URL filter.
'filter_url' => array(
'weight' => 0,
'status' => 1,
),
// Line break filter.
'filter_autop' => array(
'weight' => 1,
'status' => 1,
),
// HTML corrector filter.
'filter_htmlcorrector' => array(
'weight' => 10,
'status' => 1,
),
),
);
$text_formats['raw_html'] = array(
'format' => 'raw_html',
'name' => 'Raw HTML',
'weight' => 2,
);
foreach ($text_formats as $text_format) {
$text_format = (object) $text_format;
filter_format_save($text_format);
}
我对格式进行了细微修改,创建了一个名为 $text_formats 的数组,然后使用 foreach 循环来保存每个格式,而不是像在 standard.install 中那样单独进行。我还通常创建一个 Raw HTML 格式,该格式允许所有 HTML 标签并且没有任何过滤器应用于它,因此我在此处将其添加为要自动创建的附加格式。
添加 TinyMCE 并为某些文本格式启用它我还为每个站点下载并安装 WYSIWYG 模块和 TinyMCE 编辑器。与其必须下载并启用 WYSIWYG 模块、下载并提取 TinyMCE 库并配置编辑器,不如将其添加到我的配置文件中以使其自动完成。首先,我需要添加 WYSIWYG (http://drupal.org/project/wysiwyg) 和 Libraries API (http://drupal.org/project/libraries) 模块,并将它们添加到依赖项中以使其默认启用。
在 linuxjournal.make 中
projects[wysiwyg][type] = module
projects[wysiwyg][subdir] = contrib
projects[wysiwyg][version] = 2.1
projects[wysiwyg][download][type] = git
projects[wysiwyg][download][url] =
↪http://git.drupal.org/project/wysiwyg.git
projects[wysiwyg][download][branch] = 7.x-2.x
projects[libraries][type] = module
projects[libraries][subdir] = contrib
projects[libraries][version] = 2.0
projects[libraries][download][type] = git
projects[libraries][download][url] =
↪http://git.drupal.org/project/libraries.git
projects[libraries][download][branch] = 7.x-2.x
libraries[tinymce][type] = library
libraries[tinymce][download][type] = get
libraries[tinymce][download][url] =
↪http://github.com/downloads/tinymce/tinymce/tinymce_3.5.6.zip
在 linuxjournal.info 中
dependencies[] = libraries
dependencies[] = wysiwyg
TinyMCE 将被下载并提取到 profiles/linuxjournal/profiles 目录中,并且一旦启用 Libraries API,WYSIWYG 模块就可以访问它。但是,既然已经下载了它,我需要将其分配给我的文本格式之一才能使用它。我要将其分配到的格式是 Filtered HTML,我可以做到这一点,方法是在数据库的 wysiwyg 表中添加一条记录。我还添加了一个我在另一个站点上使用过的默认设置数组,并且已将其添加到 drupal_write_record() 函数中
// Add the TinyMCE editor to the Filtered HTML text format.
$tinymce_settings = array(
'default' => 1,
'user_choose' => 0,
'show_toggle' => 0,
'theme' => 'advanced',
'language' => 'en',
'buttons' => array(
'default' => array(
'bold' => 1,
'italic' => 1,
'strikethrough' => 1,
'justifyleft' => 1,
'justifycenter' => 1,
'justifyright' => 1,
'justifyfull' => 1,
'bulllist' => 1,
'numlist' => 1,
'link' => 1,
'unlink' => 1,
'anchor' => 1,
'image' => 1,
'formatselect' => 1,
'sup' => 1,
'sub' => 1,
'blockquote' => 1,
'code' => 1,
'hr' => 1,
'removeformat' => 1,
'charmap' => 1,
),
),
'toolbar_loc' => 'top',
'toolbar_align' => 'left',
'path_loc' => 'bottom',
'resizing' => 1,
'verify_html' => 1,
'preformatted' => 0,
'convert_fonts_to_spans' => 1,
'remove_linebreaks' => 1,
'apply_source_formatting' => 0,
'paste_auto_cleanup_on_paste' => 1,
'block_formats' => 'p,address,pre,h2,h3,h4,h5,h6,div',
'css_setting' => 'theme',
'css_path' => '',
'css_classes' => '',
);
// Create the record.
$record = array(
'format' => 'filtered_html',
'editor' => 'tinymce',
'settings' => $tinymce_settings,
);
// Save the record to the database.
drupal_write_record('wysiwyg', $record);
这里值得注意的是,$tinymce_settings 变量需要是一个标准的 PHP 数组,因为它在写入数据库表时会自动序列化。当我第一次尝试这样做时,我尝试将预序列化的数组导入到数据库中,这随后在尝试查看 WYSIWYG 管理设置表单时生成了错误。
创建其他用户角色并分配权限我们在我公司构建的所有 Drupal 站点都具有由 Workbench Moderation 模块 (http://drupal.org/project/workbench_moderation) 提供的审核工作流程。这需要为可以编辑和发布内容的用户创建一些额外的角色。我还通常创建一个 Developer 角色,供团队中任何其他 Developer 使用,该角色具有站点上所有模块的权限,以及一个 Administrator 角色,供需要比 Editors 和 Publishers 更多的管理访问权限但不需要完全 Developer 级别访问权限的用户使用。同样,我可以参考 standard.install 中的一段代码并将其用作模板
// Create new user roles for Developers, Administrators,
// Editors and Publishers.
$roles = array('Developer', 'Administrator', 'Editor', 'Publisher');
foreach ($roles as $weight => $name) {
$role = new stdClass;
$role->name = $name;
$role->weight = $weight + 2, // New roles must have at
// least a weight of 2.
// Save the new role.
user_role_save($role);
if ($name == 'Developer') {
// Give the Developer role all permissions.
user_role_grant_permissions($role->rid,
↪array_keys(module_invoke_all('permission')));
// Set this as the administrator role.
variable_set('user_admin_role', $role->rid);
// Assign user 1 the Developer role.
db_insert('users_roles')
->fields(array('uid' => 1, 'rid' => $role->rid))
->execute();
}
我创建了一个数组,其中包含我要创建的新角色的名称,然后是一个 foreach() 循环,其中包括每个项目的键,该键将用于定义每个角色的权重。第一部分适用于创建角色的所有新角色,然后还有一部分仅适用于 Developer 角色。本节将所有权限分配给 Developer 角色,并将该角色分配给用户 1。

图 6. 其他角色
创建新角色后,我现在可以设置一些默认权限
// Assign some default permissions.
$filtered_html_permission =
↪filter_permission_name($filtered_html_format);
$raw_html_permission = filter_permission_name($raw_html_format);
user_role_grant_permissions(DRUPAL_ANONYMOUS_RID,
↪array('access content', $filtered_html_permission));
user_role_grant_permissions(DRUPAL_AUTHENTICATED_RID,
↪array('access content', 'access administration menu',
↪'access devel information', $filtered_html_permission,
↪$raw_html_permission));
首先,我找出我之前创建的 Filtered HTML 和 Raw HTML 文本格式的权限名称。匿名用户将具有非常受限的权限,并且只能访问内容并使用 Filtered HTML 权限。经过身份验证的用户还可以访问 Administration Menu 和 Devel 模块的信息,以及 Filtered HTML 和 Raw HTML 文本格式。
这些只是使用安装配置文件和发行版可以完成的一些示例,并且我已经展示了自动化 Drupal 安装和配置过程的一些方法。我现在在 Nomensa 使用的完整安装配置文件还包括自定义主题以及主题模板覆盖,这些自定义主题和主题模板覆盖随后可以用于自定义面向公众和管理的主题以及其他 Drupal 配置。与每次我开始开发新站点时都必须重复相同的步骤相比,这为我在初始开发阶段节省了数小时的时间。