/[drupal]/contributions/modules/provision/platform/provision_drupal.drush.inc
ViewVC logotype

Contents of /contributions/modules/provision/platform/provision_drupal.drush.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.43 - (show annotations) (download) (as text)
Thu Nov 5 12:41:40 2009 UTC (3 weeks ago) by adrian
Branch: MAIN
Changes since 1.42: +10 -1 lines
File MIME type: text/x-php
Abstracted the functionality to prepare the $_SERVER variable into provision_prepare_environment() and additionally fix migrations
1 <?php
2 // $Id: provision_drupal.drush.inc,v 1.42 2009/10/23 10:17:10 mig5 Exp $
3 /**
4 * @file
5 * Drupal specific functions for the provisioning framework.
6 *
7 * This module is responsible for the creation and maintenance of the drupal settings.php file, the sites directory structure
8 * and all the install api code.
9 */
10
11 function provision_drupal_drush_help($section) {
12 switch ($section) {
13 case 'error:PROVISION_CONFIG_NOT_VALID' :
14 return dt('Config file could not be loaded.');
15 case 'error:PROVISION_DRUPAL_SITE_INSTALLED' :
16 return dt('Site has already been installed.');
17 case 'error:PROVISION_DRUPAL_SITE_NOT_FOUND' :
18 return dt('Site was not found.');
19 case 'error:PROVISION_DRUPAL_INSTALL_FAILED' :
20 return dt('Could not complete Drupal installation.');
21 case 'error:PROVISION_DRUPAL_UPDATE_FAILED' :
22 return dt('Could not complete Drupal update.');
23 case 'error:PROVISION_BACKUP_PATH_NOT_FOUND' :
24 return dt("Backup directory does not exist.");
25 case 'error:PROVISION_DRUPAL_INSTALL_MISSING_REQUIREMENTS' :
26 return dt("Could not meet the requirements for installing the drupal profile");
27 case 'error:PROVISION_REQUIRES_URL' :
28 return dt('You need to specify the URL argument for this command');
29 }
30
31 }
32
33 function provision_drupal_drush_engine_drupal() {
34 $engines = array();
35 $engines['install'] = array();
36 $engines['import'] = array();
37 $engines['deploy'] = array();
38 $engines['clear'] = array();
39 $engines['packages'] = array();
40 $engines['verify'] = array();
41 return $engines;
42 }
43
44 /**
45 * Initialize the platform / site
46 *
47 * This function is executed by drush_invoke, and is responsible
48 * for populating the $data context array
49 */
50 function provision_drupal_drush_init($url = NULL) {
51 $command = drush_get_command();
52 $command = explode(" ", $command['command']);
53 if ($command[0] == 'provision') {
54
55 if ($url) {
56 drush_set_option('uri' , 'http://' . $url);
57 provision_load_site_data($url);
58 drush_set_default('site_url', $url);
59 drush_set_default('profile', 'default');
60 drush_set_default('language', 'en');
61 drush_set_default('aliases', array());
62 }
63
64 define('PROVISION_CONTEXT_SITE', ($url) ? TRUE : FALSE);
65 define('PROVISION_CONTEXT_PLATFORM', !PROVISION_CONTEXT_SITE);
66 }
67 }
68
69 /**
70 * Finalize the platform / site
71 *
72 * This will run only if there were no errors in any of the previous hooks,
73 * and will allow us to cache the successful settings to the site.php/ drushrc.php
74 * files for future runs.
75 */
76 function provision_drupal_drush_exit($url = NULL) {
77 $command = drush_get_command();
78 $command = explode(" ", $command['command']);
79 if ($command[0] == 'provision') {
80 if (PROVISION_CONTEXT_SITE) {
81 if (drush_get_option('installed')) {
82 drush_set_option('site_url', drush_get_option('site_url'), 'site');
83 drush_set_option('site_id', drush_get_option('site_id'), 'site');
84 drush_set_option('client_email', drush_get_option('client_email'), 'site');
85 provision_save_site_data($url);
86 }
87 }
88 else {
89 _provision_generate_config();
90 }
91 }
92 }
93
94 /**
95 * Some commands need to have a url to operate on.
96 * This prints out a message to that effect.
97 */
98 function _provision_drupal_url_required() {
99 if (PROVISION_CONTEXT_PLATFORM) {
100 drush_set_error('PROVISION_REQUIRES_URL');
101 }
102 }
103
104 /**
105 * Validate a site exists, ie: has a settings.php file
106 *
107 * This will return an error for sites that haven't been created yet
108 */
109 function _provision_drupal_valid_site() {
110 if (PROVISION_CONTEXT_SITE) {
111 if (!_provision_drupal_site_exists(drush_get_option('site_url'))) {
112 drush_set_error('PROVISION_DRUPAL_SITE_NOT_FOUND');
113 }
114 }
115 }
116
117 /**
118 * Test to see if the site settings.php exists
119 *
120 * @param url
121 * The url of the site to check
122 * @return
123 * If the file exists, return TRUE, else return FALSE.
124 */
125 function _provision_drupal_site_exists($url) {
126 return file_exists("sites/$url/settings.php");
127 }
128
129
130 /**
131 * Validate a site has been installed, by checking it's site.php file.
132 *
133 * This will return an error for sites that haven't been installed yet
134 */
135 function _provision_drupal_valid_installed_site() {
136 if (PROVISION_CONTEXT_SITE) {
137 if (!_provision_drupal_site_installed(drush_get_option('site_url'))) {
138 drush_set_error('PROVISION_DRUPAL_SITE_NOT_FOUND');
139 }
140 }
141 }
142
143 function _provision_drupal_valid_not_installed_site() {
144 if (PROVISION_CONTEXT_SITE) {
145 if (_provision_drupal_site_installed(drush_get_option('site_url'))) {
146 drush_set_error('PROVISION_DRUPAL_SITE_INSTALLED');
147 }
148 }
149 }
150
151 /**
152 * Test to see if the site has a site.php and has it set to 'installed'
153 */
154 function _provision_drupal_site_installed($url) {
155 if (_provision_drupal_site_exists($url)) {
156 provision_load_site_data($url);
157 return drush_get_option('installed');
158 }
159 return FALSE;
160 }
161
162 /**
163 * The default template to use while generating config files.
164 *
165 * @return
166 * The default template for the config file
167 */
168 function _provision_drupal_default_template() {
169 return file_get_contents(dirname(__FILE__) .'/provision_drupal_settings.tpl.php');
170 }
171
172 /**
173 * Generate a settings file for the site.
174 *
175 * @param url
176 * The url of the site being invoked.
177 * @param data
178 * A reference to the associated array containing the data for the site. This needs to be a reference,
179 * because the modules might provide additional information about the site.
180 */
181 function _provision_drupal_create_settings_file($url = NULL) {
182 $options = drush_get_merged_options();
183
184 // As of Drupal 7 there is no more mysqli type
185 if (drush_drupal_major_version() >= 7) {
186 $options['db_type'] = ($options['db_type'] == 'mysqli') ? 'mysql' : $options['db_type'];
187 }
188
189 $options['extra_config'] = "# Extra configuration from modules:\n";
190 foreach (drush_command_implements('provision_drupal_config') as $module) {
191 $options['extra_config'] .= "# -- $module settings --\n";
192 $options['extra_config'] .= module_invoke($module, 'provision_drupal_config', $url) . "\n";
193 }
194
195
196 drush_log(dt("Generate settings.php file"));
197 if (provision_path("exists", "sites/$url/settings.php")) {
198 provision_path("chmod", "sites/$url/settings.php", 0640,
199 dt('Changed permissions of settings.php to @confirm'),
200 dt('Could not change permissions of settings.php to @confirm'));
201 }
202
203 $fp = fopen("sites/$url/settings.php", "w");
204 $text = _provision_drupal_default_template();
205 fwrite($fp, "<?php\n". provision_render_config($text, $options));
206 fclose($fp);
207
208 # Change the permissions of the file
209 provision_path("chmod", "sites/$url/settings.php", 0440,
210 dt('Changed permissions of settings.php to @confirm'),
211 dt('Could not change permissions of settings.php to @confirm'));
212
213 provision_path("chgrp", "sites/$url/settings.php", drush_get_option('web_group'),
214 dt('Change group ownership of settings.php to @confirm'),
215 dt('Could not change group ownership of settings.php to @confirm'));
216 }
217
218 /**
219 * Create the directories needed to host a drupal site
220 *
221 * Also maintains permissions on existing directories.
222 */
223 function _provision_drupal_create_directories($url, $profile = NULL) {
224 $paths = array(
225 "sites/$url" => 0755,
226 "sites/$url/files" => 02770,
227 "sites/$url/files/tmp" => 02770,
228 "sites/$url/files/images" => 02770,
229 "sites/$url/files/pictures" => 02770,
230 "sites/$url/themes" => 0755,
231 "sites/$url/modules" => 0755,
232 );
233 $grps = array(
234 "sites/$url/files",
235 "sites/$url/files/tmp",
236 "sites/$url/files/images",
237 "sites/$url/files/pictures",
238 );
239
240 foreach ($paths as $path => $perm) {
241 if (!is_dir($path)) {
242 provision_path("mkdir", $path, TRUE,
243 dt("Created <code>@path</code>"),
244 dt("Could not create <code>@path</code>"),
245 'DRUSH_PERM_ERROR');
246 }
247
248 provision_path("chmod_recursive", $path, $perm,
249 dt("Changed permissions of <code>@path</code> to @confirm"),
250 dt("Could not change permissions <code>@path</code> to @confirm")
251 );
252 }
253 foreach ($grps as $path) {
254 provision_path("chown_recursive", $path, drush_get_option('script_user'),
255 dt("Changed ownership of <code>@path</code>"),
256 dt("Could not change ownership <code>@path</code>"),
257 'DRUSH_PERM_ERROR' );
258 provision_path("chgrp_recursive", $path, drush_get_option('web_group'),
259 dt("Changed group ownership of <code>@path</code>"),
260 dt("Could not change group ownership <code>@path</code>"));
261 }
262 }
263
264 /**
265 * Runs an external script to reload all the various drupal caches
266 */
267 function _provision_drupal_rebuild_caches($url = NULL) {
268 if (PROVISION_CONTEXT_SITE) {
269 drush_include_engine('drupal', 'clear');
270 }
271 }
272
273
274 /**
275 * Find available profiles on this platform.
276 */
277 function _provision_find_profiles() {
278 include_once('includes/install.inc');
279
280 if (!$dir = opendir("./profiles")) {
281 drush_log(dt("Cannot find profiles directory"), 'error');
282 return FALSE;
283 }
284 while (FALSE !== ($name = readdir($dir))) {
285 $languages = array();
286 $file = "./profiles/$name/$name.profile";
287 if ($name == '..' || $name == '.' || !file_exists($file)) {
288 continue;
289 }
290 $profile = new stdClass();
291 $profile->name = $name;
292 $profile->filename = $file;
293
294 _provision_cvs_deploy($profile);
295 require_once($profile->filename);
296 $func = $profile->name . "_profile_details";
297 if (function_exists($func)) {
298 $profile->info = $func();
299 }
300
301 $languages['en'] = 1;
302 // Find languages available
303 $files = array_keys(drush_scan_directory('./profiles/' . $name . '/translations', '/\.po$/', array('.', '..', 'CVS'), 0, FALSE, 'filepath'));
304 $files = array_merge($files, array_keys(drush_scan_directory('./profiles/' . $name , '/\.po$/', array('.', '..', 'CVS'), 0, FALSE, 'filepath')));
305 if (is_array($files)) {
306 foreach ($files as $file) {
307 if (preg_match('!(/|\.)([^\./]+)\.po$!', $file, $langcode)) {
308 $languages[$langcode[2]] = 1; // use the language name as an index to weed out duplicates
309 }
310 }
311 }
312 $profile->info['languages'] = array_keys($languages);
313 $return[$name] = $profile;
314 drush_log(dt('Found install profile %name', array('%name' => $name)));
315 }
316
317 return $return;
318
319 }
320
321 function provision_drupal_find_sites() {
322 if ($dir = opendir("./sites")) {
323 while (FALSE !== ($subdir = readdir($dir))) {
324 // skip internal directory pointers
325 if ($subdir != '.' && $subdir != '..') {
326 $file = "./sites/$subdir/settings.php";
327 if (file_exists("$file") && ($subdir != 'default') && !is_link("./sites/$subdir")) {
328 $sites[$subdir] = $file;
329 }
330 }
331 }
332 closedir($dir);
333 } else {
334 drush_log(dt("Cannot find sites directory"), 'error');
335 $sites = FALSE;
336 }
337 return $sites;
338 }
339
340 function _provision_drupal_get_cvs_versions($files) {
341 foreach ($files as $modulename => $file) {
342 $project = array();
343 $project['filename'] = $file->filename;
344 $project['name'] = $file->name;
345 $file->info['description'] = str_replace("\n", "", $file->info['description']);
346 if (!isset($project['project'])) {
347 $project['project'] = cvs_deploy_get_project_name($project);
348 }
349 _cvs_deploy_version_alter($file->info['version'], $project);
350 $name = !empty($project['project']) ? $project['project'] : $modulename;
351 $files[$name] = $file;
352 }
353
354 return $files;
355 }
356
357 /**
358 * Create and remove symlinks for each of the possible domain aliases of an existing site
359 */
360 function _provision_drupal_maintain_aliases($url) {
361 if (PROVISION_CONTEXT_SITE) {
362 // First we delete all the old aliases
363 _provision_drupal_delete_aliases(drush_get_option('aliases', array(), 'site'));
364
365 if (!drush_get_option('redirection')) {
366 $aliases = drush_get_option('aliases');
367 if (!is_array($aliases)) {
368 $aliases = explode(",", $aliases);
369 }
370 foreach($aliases as $alias) {
371 if (trim($alias)) {
372 provision_path("symlink", $url, drush_get_option('docroot_path') . "/sites/" . $alias,
373 dt("Created symlink for alias @alias", array("@alias" => $alias)),
374 dt("Could not create symlink for alias @alias", array("@alias" => $alias)));
375 }
376 }
377 }
378 }
379 }
380
381 /**
382 * Delete a list of aliases
383 */
384 function _provision_drupal_delete_aliases($aliases) {
385 if (!is_array($aliases)) {
386 $aliases = explode(",", $aliases);
387 }
388 foreach ($aliases as $alias) {
389 if (trim($alias)) {
390 provision_path("unlink", drush_get_option('docroot_path') . "/sites/" . $alias, TRUE,
391 dt("Removed symlink for alias @alias", array("@alias" => $alias)),
392 dt("Could not remove symlink for alias @alias", array("@alias" => $alias)));
393 }
394 }
395 }
396
397 require_once('cvs_deploy.inc');
398
399 function provision_find_packages() {
400 // Load the version specific include files.
401 drush_include_engine('drupal', 'packages', drush_drupal_major_version());
402
403 $packages['base'] = _provision_find_packages('base');
404
405 // Create a package for the Drupal release
406 $packages['base']['platforms'] = _provision_find_platforms();
407
408 // Find install profiles.
409 $profiles = _provision_find_profiles();
410 drush_set_option('profiles', array_keys((array) $profiles), 'drupal');
411
412 // Iterate through the install profiles, finding the profile specific packages
413 foreach ($profiles as $profile => $info) {
414 _provision_cvs_deploy($info);
415 if (!$info->version) {
416 $info->version = drush_drupal_version();
417 }
418 $packages['base']['profiles'][$profile] = $info;
419 $packages['profiles'][$profile] = _provision_find_packages('profiles', $profile);
420 }
421
422 // Iterate through the sites, finding site specific packages
423 foreach (drush_get_option('sites', array()) as $site) {
424 $packages['sites'][$site] = _provision_find_packages('sites', $site);
425 }
426 return $packages;
427 }
428
429 function _provision_find_platforms() {
430 return array(
431 'drupal' => array(
432 'short_name' => 'drupal', 'version' => drush_drupal_version(),
433 'description' => dt("This platform is running @short_name @version", array('@short_name' => 'Drupal', '@version' => VERSION))));
434 }
435
436 /**
437 * A small helper function to reduce code duplication
438 */
439 function _provision_find_packages($scope, $key = '') {
440 $packages = array();
441 $scope_text = ($key) ? "$scope/$key" : $scope;
442 foreach (array('modules', 'themes') as $type) {
443 $packages[$type] = array();
444 $func = "_provision_drupal_find_$type";
445 $result = $func($scope, $key);
446 if (sizeof($result)) {
447 $packages[$type] = $result;
448 drush_log(dt("Found !count !type in !scope",
449 array('!count' => sizeof($result),
450 '!scope' => $scope_text, '!type' => $type)));
451 }
452 }
453 return $packages;
454 }
455
456 /**
457 * Map the system table to a packages multi-dimensional array component
458 */
459 function provision_drupal_system_map() {
460 // Load the version specific include files.
461 drush_include_engine('drupal', 'packages');
462
463 $profiles = _provision_find_profiles();
464 foreach ($profiles as $profile => $info) {
465 _provision_cvs_deploy($info);
466 if (!$info->version) {
467 $info->version = drush_drupal_version();
468 }
469 $profiles[$profile] = $info;
470 }
471 $packages['platforms'] = _provision_find_platforms();
472
473 $profile = drush_get_option('profile');
474 $packages['profiles'][$profile] = $profiles[$profile];
475 $packages['profiles'][$profile]->status = 1;
476
477 foreach (_provision_system_query("module") as $module) {
478 $info_file = sprintf("%s/%s.info", dirname($module->filename), $module->name);
479 $module->info = provision_parse_info_file($info_file);
480
481 _provision_cvs_deploy($module);
482 $module->filename = realpath($module->filename);
483 if ($module->schema_version == -1) {
484 $module->schema_version = 0;
485 }
486 $packages['modules'][$module->name] = $module;
487 }
488
489 drush_log(dt("Found !count modules", array('!count' => sizeof($packages['modules']))));
490
491 foreach (_provision_system_query("theme") as $theme) {
492 $info_file = sprintf("%s/%s.info", dirname($theme->filename), $theme->name);
493 $theme->info = provision_parse_info_file($info_file);
494 _provision_cvs_deploy($theme);
495 $theme->filename = realpath($theme->filename);
496
497 if ($theme->schema_version == -1) {
498 $theme->schema_version = 0;
499 }
500
501 $packages['themes'][$theme->name] = $theme;
502 }
503 drush_log(dt("Found !count themes", array('!count' => sizeof($packages['themes']))));
504 return $packages;
505 }
506
507 /**
508 * Retrieve a list of paths to search in a certain scope
509 */
510 function _provision_drupal_search_paths($scope, $key = '', $type = 'modules') {
511 $searchpaths = array();
512 $drupal_root = drush_get_context('DRUSH_DRUPAL_ROOT');
513 switch ($scope) {
514 case 'base' :
515 $searchpaths[] = sprintf("%s/%s", $drupal_root, $type);
516 $searchpaths[] = sprintf("%s/sites/all/%s", $drupal_root, $type);
517 break;
518 default :
519 if ($key) {
520 $searchpaths[] = sprintf("%s/%s/%s/%s", $drupal_root, $scope, $key, $type);
521 }
522 break;
523
524 }
525 return $searchpaths;
526 }
527
528 /**
529 * Find modules in a certain scope.
530 *
531 * This function is general enough that it works for all supported
532 * versions of Drupal.
533 */
534 function _provision_drupal_find_modules($scope, $key = '') {
535 $paths = _provision_drupal_search_paths($scope, $key, 'modules');
536 $files = array();
537 foreach ($paths as $path) {
538 $files = array_merge($files, drush_scan_directory($path, "/\.module$/", array('.', '..', 'CVS', '.svn'), 0, true, 'name'));
539 }
540 foreach ($files as $name => $info) {
541 $install_file = sprintf("%s/%s.install", dirname($info->filename), $name);
542 $schema_version = 0;
543 if (file_exists($install_file)) {
544 $source = file_get_contents(trim($install_file));
545 $source = str_replace("\r\n", "\n", $source);
546 $source = str_replace("\r", "\n", $source);
547 $function_matches = array();
548 preg_match_all('!function\s*&?([a-zA-Z0-9_]+)_update_([0-9]+)\(.*?\s*\{!', $source, $function_matches);
549
550 if (sizeof($function_matches[0])) {
551 $schema_version = max($function_matches[2]);
552 }
553 }
554 $info_file = sprintf("%s/%s.info", dirname($info->filename), $name);
555 $files[$name]->info = provision_parse_info_file($info_file);
556 $files[$name]->schema_version = $schema_version;
557 _provision_cvs_deploy($files[$name]);
558 }
559 return $files;
560 }
561
562 function provision_parse_info_file($filename) {
563 $info = array();
564
565 $defaults = array(
566 'dependencies' => array(),
567 'description' => '',
568 'version' => NULL,
569 'php' => DRUPAL_MINIMUM_PHP,
570 );
571
572 if (file_exists($filename)) {
573 $info = _provision_drupal_parse_info_file($filename);
574 }
575
576 // Merge in defaults and return
577 return $info + $defaults;
578 }
579
580 /**
581 * Set up the $_SERVER environment variable so that drupal can correctly parse the settings.php file
582 */
583 function provision_prepare_environment() {
584 $fields = array('db_type', 'db_host', 'db_user', 'db_passwd', 'db_name');
585 foreach ($fields as $key) {
586 $_SERVER[$key] = drush_get_option($key, null, 'site');
587 }
588 }

  ViewVC Help
Powered by ViewVC 1.1.2