Commit 969d587a authored by anarcat's avatar anarcat

move subdir implementation to the Apache service

the reasoning is that we need to operate on multiple servers, which
can't be done outside of services.

furthermore, we had to move to a Config class for sync to work, and we
hack up that class badly so that it is forced to generate multiple
configuration files instead of just one, which is impure and weird,
but seems to work in my first tests.

we still need to reimplement sites.php and disabled sites support, but
multi-server should work better now

see #2020075 and #2020079
parent dcd3b2db
<?php
/**
* Base class for subdir support.
*
* This class will publish the config files to remote
* servers automatically.
*/
class Provision_Config_Apache_Subdir extends Provision_Config_Http {
public $template = 'subdir.tpl.php';
public $description = 'subdirectory support';
// hack: because the parent class doesn't support multiple config
// files, we need to keep track of the alias we're working on.
protected $current_alias;
function write() {
foreach (d()->aliases as $alias) {
if (strpos($alias, '/')) {
$this->current_alias = $alias;
drush_log("Subdirectory alias `$alias` found. Creating configuration files.", 'notice');
$uri_path = $this->data['http_subdird_path'] . '/' . $this->uri();
provision_file()->create_dir($uri_path, dt("Webserver subdir configuration for domain"), 0700);
$this->context->platform->server->sync($uri_path, array(
'exclude' => $uri_path . '/*', // Make sure remote directory is created
));
parent::write();
}
}
}
/**
* Guess the URI this subdir alias is related too.
*/
function uri() {
return explode('/', $this->current_alias, 2)[0];
}
/**
* Guess the subdir part of the subdir alias.
*/
function subdir() {
return explode('/', $this->current_alias, 2)[1];
}
function process() {
parent::process();
$this->data['uri'] = $this->uri();
$this->data['subdir'] = $this->subdir();
}
function filename() {
return $this->data['http_subdird_path'] . '/' . $this->uri() . '/' . $this->subdir() . '.conf';
}
}
Alias /<?php print $location; ?> <?php print $platform_path; ?>
Alias /<?php print $subdir; ?> <?php print $platform_path; ?>
<Location /<?php print $location; ?>>
<Location /<?php print $subdir; ?>>
SetEnv db_type <?php print urlencode($db_type); ?>
......
......@@ -17,6 +17,7 @@ class Provision_Service_http_apache extends Provision_Service_http_public {
$this->configs['server'][] = 'Provision_Config_Apache_Server';
$this->configs['platform'][] = 'Provision_Config_Apache_Platform';
$this->configs['site'][] = 'Provision_Config_Apache_Site';
$this->configs['site'][] = 'Provision_Config_Apache_Subdir';
}
/**
......
......@@ -15,6 +15,7 @@ class Provision_Service_http_public extends Provision_Service_http {
$data['http_postd_path'] = $this->server->http_postd_path;
$data['http_platformd_path'] = $this->server->http_platformd_path;
$data['http_vhostd_path'] = $this->server->http_vhostd_path;
$data['http_subdird_path'] = $this->server->http_subdird_path;
}
$data['http_port'] = $this->server->http_port;
......@@ -54,6 +55,7 @@ class Provision_Service_http_public extends Provision_Service_http {
$this->server->http_postd_path = "{$app_dir}/post.d";
$this->server->http_platformd_path = "{$app_dir}/platform.d";
$this->server->http_vhostd_path = "{$app_dir}/vhost.d";
$this->server->http_subdird_path = "{$app_dir}/subdir.d";
$this->server->http_platforms_path = "{$this->server->aegir_root}/platforms";
}
}
......@@ -89,6 +91,11 @@ class Provision_Service_http_public extends Provision_Service_http {
$this->sync($this->server->http_vhostd_path, array(
'exclude' => $this->server->http_vhostd_path . '/*', // Make sure remote directory is created
));
provision_file()->create_dir($this->server->http_subdird_path, dt("Webserver subdir configuration"), 0700);
$this->sync($this->server->http_subdird_path, array(
'exclude' => $this->server->http_subdird_path . '/*', // Make sure remote directory is created
));
}
parent::verify_server_cmd();
......
<?php
/**
* Implements hook_drush_init().
*/
function subdirs_drush_init() {
subdirs_provision_register_autoload();
}
/**
* Register our directory as a place to find Provision classes.
*
* This allows Provision to autoload our classes, so that we don't need to
* specifically include the files before we use the class.
*/
function subdirs_provision_register_autoload() {
static $loaded = FALSE;
if (!$loaded) {
$loaded = TRUE;
provision_autoload_register_prefix('Provision_', dirname(__FILE__));
}
}
/**
* Implements drush_hook_pre_provision_install().
*/
function drush_subdirs_pre_provision_install() {
_subdirs_create_site_configs();
}
/**
* Implements drush_hook_pre_provision_install_rollback().
*/
function drush_subdirs_pre_provision_install_rollback() {
_subdirs_remove_site_configs();
}
/**
* Implementation of drush_hook_pre_provision_verify()
*/
function drush_subdirs_pre_provision_verify() {
_subdirs_create_site_configs();
}
/**
* Implementation of drush_hook_post_provision_deploy()
*/
function drush_subdirs_pre_provision_deploy() {
_subdirs_create_site_configs();
}
/**
* Implementation of drush_hook_provision_delete()
*/
function drush_subdirs_pre_provision_delete() {
_subdirs_remove_site_configs();
}
/**
* Implementation of drush_hook_provision_disable()
*/
function drush_subdirs_pre_provision_disable() {
_subdirs_disable_sites();
}
/**
* Implements drush_hook_pre_provision_enable().
*/
function drush_subdirs_pre_provision_enable() {
_subdirs_create_site_configs();
}
/**
* Implements hook_provision_config_load_templates().
*/
function subdirs_provision_config_load_templates($config) {
if ($config->template == 'provision_drupal_sites.tpl.php') {
$context = d();
$use_subdirs_tpl = FALSE;
foreach ($context->aliases as $alias) {
if (strpos($alias, '/')) {
$use_subdirs_tpl = TRUE;
}
}
if ($use_subdirs_tpl) {
drush_log('Generating sites.php for use with subdirectories.', 'notice');
return dirname(__FILE__) . '/Provision/Config/subdirs_drupal_sites.tpl.php';
}
}
}
/**
* Helper function to create configuration files for subdirectories.
*/
function _subdirs_create_site_configs() {
if (d()->type == 'site') {
$aliases = d()->aliases;
if (count($aliases)) {
foreach ($aliases as $alias) {
if (strpos($alias, '/')) {
drush_log("Subdirectory alias `$alias` found. Creating configuration files.", 'notice');
_subdirs_create_site_location($alias);
_subdirs_create_domain_vhost($alias);
_subdirs_create_symlinks($alias, d()->uri);
}
}
}
}
}
/**
* Helper function to remove configuration files for subdirectories.
*/
function _subdirs_remove_site_configs() {
$context = d();
$aliases = $context->aliases;
$subdirs_path = $context->server->http_app_path . '/subdirs.d';
if (count($aliases)) {
foreach ($aliases as $alias) {
_subdirs_delete_site_location($alias);
// We only want to remove the domain vhost after the last subdirectory
// site has been deleted.
$alias_parts = explode('/', $alias, 2);
$includes_path = $subdirs_path . '/' . $alias_parts[0];
if ($handle = opendir($includes_path)) {
if (FALSE === readdir($handle)) {
_subdirs_delete_domain_vhost($alias);
_subdirs_delete_symlinks($alias);
}
}
}
}
}
/**
* Create the config file for the subdirectory.
*/
function _subdirs_create_site_location($alias) {
$alias_parts = explode('/', $alias, 2);
$context = d();
// Generate variables to pass to template
$variables = array('db_type', 'db_name', 'db_user', 'db_passwd', 'db_host', 'db_port');
foreach ($variables as $key => $value) {
$variables[$value] = drush_get_option($value, NULL, 'site');
unset($variables[$key]);
}
$variables['site_path'] = $context->site_path;
$variables['platform_path'] = $context->platform->root;
$variables['location'] = $alias_parts[1];
$output = _subdirs_render_template('site_location.tpl.php', $variables);
// Create the relevant include paths
$subdirs_path = $context->server->http_app_path . '/subdirs.d';
if (!is_dir($subdirs_path)) {
mkdir($subdirs_path);
}
$includes_path = $subdirs_path . '/' . $alias_parts[0];
if (!is_dir($includes_path)) {
mkdir($includes_path);
}
$location_path = $includes_path . '/' . $alias_parts[1] . '.conf';
if (fwrite(fopen($location_path, 'w'), $output)) {
drush_log('Created site location config file for subdirectory ' . $alias . ' at ' . $location_path, 'success');
}
else {
drush_log('Error encountered attempting to create site location config file for subdirectory ' . $alias, 'error');
}
}
/**
* Create the vhost for the subdirectory domain.
*/
function _subdirs_create_domain_vhost($alias) {
$alias_parts = explode('/', $alias, 2);
$context = d();
// Generate variables to pass to template
$variables = array(
'http_port' => $context->server->http_port,
'subdirs_path' => $context->server->http_app_path . '/subdirs.d',
'uri' => $alias_parts[0],
);
$output = _subdirs_render_template('domain_vhost.tpl.php', $variables);
$domain_vhost_path = $context->server->http_vhostd_path . '/' . $alias_parts[0];
if (fwrite(fopen($domain_vhost_path, 'w'), $output)) {
drush_log('Created domain vhost for subdirectory ' . $alias . ' at ' . $domain_vhost_path, 'success');
}
else {
drush_log('Error encountered attempting to create domain vhost for subdirectory ' . $alias, 'error');
}
}
/**
* Helper function to remove configuration files for subdirectories.
*/
function _subdirs_disable_sites() {
$aliases = d()->aliases;
if (count($aliases)) {
foreach ($aliases as $alias) {
if (strpos($alias, '/')) {
drush_log("Disabling subdirectory site $alias.", 'notice');
_subdirs_create_disabled_site_location($alias);
}
}
}
}
/**
* Create the config file for the disabled subdirectory.
*/
function _subdirs_create_disabled_site_location($alias) {
$alias_parts = explode('/', $alias, 2);
$context = d();
// Generate variables to pass to template
$variables['location'] = $alias_parts[1];
$variables['web_disable_url'] = $context->platform->server->web_disable_url;
$variables['uri'] = $context->uri;
$output = _subdirs_render_template('site_location_disabled.tpl.php', $variables);
$subdirs_path = $context->server->http_app_path . '/subdirs.d';
$includes_path = $subdirs_path . '/' . $alias_parts[0];
$location_path = $includes_path . '/' . $alias_parts[1] . '.conf';
if (fwrite(fopen($location_path, 'w'), $output)) {
drush_log('Created disabled site location config file for subdirectory ' . $alias . ' at ' . $location_path, 'success');
}
else {
drush_log('Error encountered attempting to create disabled site location config file for subdirectory ' . $alias, 'error');
}
}
/**
* Delete the config file for the subdirectory.
*/
function _subdirs_delete_site_location($alias) {
$alias_parts = explode('/', $alias, 2);
$context = d();
$subdirs_path = $context->server->http_app_path . '/subdirs.d';
$includes_path = $subdirs_path . '/' . $alias_parts[0];
$location_path = $includes_path . '/' . $alias_parts[1] . '.conf';
if (unlink($location_path)) {
drush_log('Deleted site location config file for subdirectory ' . $alias, 'success');
}
else {
drush_log('Error encountered attempting to delete site location config file for subdirectory ' . $alias, 'error');
}
}
/**
* Delete the vhost for the subdirectory domain.
*/
function _subdirs_delete_domain_vhost($alias) {
$alias_parts = explode('/', $alias, 2);
$context = d();
$domain_vhost_path = $context->server->http_vhostd_path . '/' . $alias_parts[0];
if (unlink($domain_vhost_path)) {
drush_log('Deleted domain vhost for subdirectory ' . $alias, 'success');
}
else {
drush_log('Error encountered attempting to delete domain vhost for subdirectory ' . $alias, 'error');
}
}
/**
* Create subdirectory symlinks
*
* This create a sites/example.com.foo symlink pointing to the main
* URL of the site.
*/
function _subdirs_create_symlinks($alias, $main) {
provision_file()->symlink($main, 'sites/' . str_replace('/', '.', $alias))
->succeed('symlinked @path to @target')
->fail('failed to symlink @path to @target');
}
/**
* Delete subdirectory symlinks
*
* This deletes the symlinks created by _subdirs_create_symlinks().
*/
function _subdirs_delete_symlinks($alias) {
provision_file()->unlink('sites/' . str_replace('/', '.', $alias))
->succeed('removed @path symlink')
->fail('failed to remove @path symlink');
}
/**
* Render our config file templates.
*/
function _subdirs_render_template($template, $variables) {
// TODO: Remove this, once we've got a working Config class.
$template_path = dirname(__FILE__) . '/Provision/Config/' . $template;
extract($variables);
ob_start();
include $template_path;
$content = ob_get_clean();
return $content;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment