Hi,
Trying to work in a maintainable way, I use install profiles for all my projects to stage well. In the one I have to build today I need to use this great module.
If I understood well how to export domain's configuration to my features, I did not found any solution to enable the module at installation time. I tried to add an install task to write into the settings.php file but it make the install process crash before the end.
/**
* Implements hook_install_tasks().
*/
function myprofile_install_tasks() {
return array(
'enable_domain' => array(
'display_name' => 'Enable Domain Access',
'display' => TRUE,
'type' => 'normal',
'run' => INSTALL_TASK_RUN_IF_NOT_COMPLETED,
'function' => '_myprofile_install_enable_domain',
),
);
}
/**
* Install task "enable_domain" callback.
*
* Add domain specific code inclusion in settings.php.
*/
function _myprofile_install_enable_domain() {
// Define settings.php file to use
$settings_file = DRUPAL_ROOT . '/' . conf_path() . '/settings.php';
// Save its actual permissions
$perms = substr(sprintf('%o', fileperms($settings_file)), -4);
// Make it writable
chmod($settings_file, 0777);
// Open it to append content
$f = fopen($settings_file, 'a');
if ($f) {
$path = '/' . drupal_get_path('module', 'domain') . '/settings.inc';
if (is_file(DRUPAL_ROOT . $path)) {
fputs($f, "\n");
fputs($f, '/**' . "\n");
fputs($f, ' * Add the domain module setup routine.' . "\n");
fputs($f, ' */' . "\n");
fputs($f, 'include DRUPAL_ROOT . \'' . $path . '\';' . "\n");
}
}
// Reset settings file permissions
chmod($settings_file, $perms);
}
Does someone have an idea to achieve this ?
Shall we need to add a test in settings.inc (or in settings.php) to avoid bootstrapping while installation is not over ? (inspiration #1917440: Front Page not working with some web server configurations)
Comments
Comment #1
agentrickardI think you have to do that outside of Drupal, actually. Do you have a build script? I use this bash script as part of my local setup:
You can safely add these lines to settings.php before installing the module. The module is smart enough not to fire if it is not enabled.
See also #1823190: Do not create default domain on installation, which is related if not identical.
Comment #2
duaelfrThank you for your advice but I don't think the other issue is identical because I am complaining about the fact that if the include is in the settings.php before the installation of Drupal, it will crash. In this issue, the problem is just that there is a domain created upon installation of the module.
The idea of using a build script isn't too bad but it cannot work on a distribution context. You cannot ship an install profile and say to people using it to run a script on their server (what if they can't ?).
I really think we can find a way to avoid this include to interfere with the install process. Do you see a condition I could wrap the inclusion into for my particular use case ?
What would be the side effects of writing this ?
Thanks for your help.
Comment #3
agentrickardWrapping the include call in a conditional should be fine. It is not recommended because it would, in many cases, confuse people.
We could also move the IF to the DOMAIN_BOOTSTRAP_INIT phase of _domain_bootstrap(). Currently, we assume a database has been installed.
We could at least ensure that $databases is not empty. I think there is a separate issue for disabling the auto-creation of a default domain.
Comment #4
duaelfrThe idea was good but you can have a $databases array while Drupal is not installed yet.
Your patch would work in the majority of the cases but people dealing with distributions often keep their settings.php file intact while re-installing the website. People playing with deployment systems like Aegir often use their system to create the database and generate the settings.php file before launching the installation.
Here is a common use case for developpers trying to apply best practices :
Thank you very much for your interest in this issue.
Comment #5
agentrickardHow about we use some other $conf flag here then?
Comment #6
duaelfrI don't think we can rely on any $conf flag here...
Is it an useful database call for domain that could be made in a try {} catch block, before anything else, and which could stop the domain process if it catches an Exception ?
Comment #7
agentrickardOooo. Fancy, but sounds good. That code was originally written in Drupal 5 ;-)
Comment #8
duaelfrGreat !
Can't wait for your patch :)
Comment #9
agentrickardI think you mean _your_ patch ;-)
Comment #10
duaelfrYou got me !
I'll try to find the time and the best way to achieve this.
Comment #11
agentrickardWell, if the database is not instantiated, db_query() won't load, so this small patch works.
We might also do a try/catch in addition.
Comment #12
agentrickardHere's a version with both.
Comment #13
duaelfrYour last patch does not change anything for me.
I found a clue in this issue #1562662: site-install : MAINTENANCE_MODE defined too late but as I said when reoppening it, it does not work anymore.
The
drupal_installation_attempted()function looks great for our use case anyway.Comment #14
agentrickardI don't quote understand the error you're getting. The patch above should short-circuit any Domain loading. The error you are now reporting sounds like a Drush issue.
Are you getting any errors from Domain module code?
Comment #15
duaelfrMy errors come from the
drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE, $new_phase);line.When I force a return juste before this line my install process is running well.
The error occurs when the bootstrap tries to read the blocked_ips database table.
Comment #16
agentrickardIs $new_phase FALSE or TRUE in your case? What happens when you force it to be the other option? (See the comment block from lines 97-102).
Comment #17
duaelfrI will try it asap
Comment #18
agentrickardI suggest that because we've had issues in the past (documented in the comments) where the $new_phase has to be set specifically based on the calling condition. Right now, we don't account for "installing". So forcing a change there may fix the issue.
Comment #19
duaelfrSorry I had no time for this for now. I hope to be able to give you some feedback next week.
Thank you.
Comment #20
tche082 commentedi am running into the exact same problem.
my database array has been defined and using drupal_installation_attempted() does not work as the maintenance mode is set in a later stage.
what i am trying to do is to build a deployment script like this so i can run it multiple times on different servers
# Deployment Script
# Set up initial drupal environment
drush si -y local_profile --account-pass="local" --sites-subdir="default"
# enable the domain module
drush pm-enable domain --uri=http://local.com.hk/
Comment #21
agentrickardSee comments 15 and 16 for testing options.
Comment #22
davidsonjames commentedI've added a couple of lines in which checks the global $install_state. If thats populated we don't want to run the bootstrap as the installation isn't complete.
I've tested it locally and it allows you to add in include in your settings file, and have domain access be a dependancy in your installation profile.
Comment #23
duaelfrThanks for your patch david but you may include a full patch against the last dev version to keep this issue list clean, not just an interdiff.
Comment #24
mstef commentedPatch #22 still gives me "Fatal error: Call to undefined function db_query().." when trying to install a site.
This worked for me:
Comment #25
agentrickardWouldn't db_table_exists() be a better check?
Comment #26
mstef commentedNo, because if the function db_query() is not available, neither is db_table_exists().
Comment #27
agentrickardMakes sense. This needs some review.
Comment #28
FreekVR commentedI originally applied the patch in #12 to fix issues I had when installing using drush site-install. I needed to also wrap my settings.inc include in my settings.php in an if (!empty($databases)) statement. This worked fine, until I started automatically enabling some features containing domain config, along with enabling the domain module and some additional domain contrib modules.
This caused an "Error: Call to undefined function domain_get_primary_table() " due to the settings.inc not being loaded. Because at that point, settings.php HAD been adjusted with a filled $databases array, but had not been reloaded, and thus the domain bootstrap hadn't been included.
To fix this, I applied the patch from #22 also. I also removed the if (!empty($databases)) statement from my settings.php. This succesfully allowed me to install my site along with the domain config.
Attached is a patch containing fixes from those two commenters, applied against the latest dev. I've also slightly modified the comments in the file to reflect the changes made.
Comment #29
agentrickardUsing $install_state is smart. There is a typo in the comments.
Comment #30
nevergoneCorrected typo in #28.
The patch tested the latest Domain Access module from Git (7.x-3.x) and Drush 6.x.
Drush commands for testing: sqlc, cron, cc all, pm-enable, sql-dump
The patch works well!
Thanks!
Comment #31
rob c commentedStill works, dare i to ...
Comment #32
duaelfr+1
Comment #33
agentrickardMarking for inclusion after some review.
Comment #34
agentrickardCommitted.
Nice work, all.
Comment #37
Andreas Radloff commentedThis did not work for me using Drush 7. I had to populate install_state manually in settings.php:
Comment #38
goz commentedI have some issues with code of @DuaelFR in #0.
I found another way, based on @andreas-radloff code #37 for the drush install.
And for UI install, MAINTENANCE_MODE is setted, so we don't want to load domain settings. But we load it in our tasks before enabling domain module.
Here is my code which allow to install domain from profile install with UI and drush :
In myprofile.profile file.
Here is my settings.php file :
Comment #39
bdlangton commented#38 fixed it for me. Thanks GoZ!
Comment #40
boosmith commentedYes #38 fixed it for me too. Thanks @Goz