/[drupal]/contributions/modules/multisite_manager/multisite_manager.module
ViewVC logotype

Diff of /contributions/modules/multisite_manager/multisite_manager.module

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

revision 1.8, Fri Feb 8 22:11:51 2008 UTC revision 1.8.4.1, Wed Mar 12 16:47:45 2008 UTC
# Line 1  Line 1 
1  <?php  <?php
2  // $Id: multisite_manager.module,v 1.7 2008/02/08 20:25:25 schuyler1d Exp $  // $Id: multisite_manager.module,v 1.8 2008/02/08 22:11:51 schuyler1d Exp $
3    
4  /**  /**
5   * author: Schuyler Duveen   * author: Schuyler Duveen
6   * sponsor: Columbia Univeristy Center for New Media Teaching & Learning   * sponsor: Columbia Univeristy Center for New Media Teaching & Learning
7   * URL: http://drupal.org/project/multisite_manager   * URL: http://drupal.org/project/multisite_manager
8   * License: GPL v2 or any later version (see LICENSE.txt)   * License: GPL v2 or any later version
9   *   *
10   * TODO   * TODO
11   * ----   * ----
12   * test postgres   * test postgres
13   * actual 'management' options?   * actual 'management' options?
14   * update.php support   * update.php support
15     * document settings.php setup
16     * configuration to run as different DB user when creating DB and granting privileges
17     * hook_before_site_install($node);
18     * hook_after_site_install($node);
19   */   */
20    
21  /**  /**
# Line 20  Line 24 
24  function multisite_manager_help($section) {  function multisite_manager_help($section) {
25    switch ($section) {    switch ($section) {
26      case 'admin/help#multisite_manager':      case 'admin/help#multisite_manager':
27        return t('Multisite Manager helps create new drupal sites from within a main drupal site.  For documentation see http://code.google.com/p/drupal-multisite-manager/');      case 'admin/settings/multisite_manager':
28          return t('Multisite Manager helps create new drupal sites from within a main drupal site.  For documentation see <a href="http://drupal.org/project/multisite_manager">http://drupal.org/project/multisite_manager</a>.<p>This module is <b>NOT Plug-n-Play</b>. Before this module will work as desired follow these steps:<ol><li>Configure the Multisite Manager defaults for where new sites will be added to the database.</li><li>Make a special settings.php file in the /sites/ drupal directory. (This '. l( 'tool','admin/settings/multisite_manager/phpsettingfile') . ' will help)</li><li>Change your Apache config, probably in your Drupal .htaccess file.</li><li>For the default setup you need a symlink in your main Drupal directory.  After changing to that directory, run <code>$ ln -s . site</code></li><li>Lastly, the DB account that runs the main site must have extra DB permissions to create databases and grant privileges</li></ol></p>');
29    }    }
30  }  }
31    
# Line 53  function multisite_manager_cron() { Line 58  function multisite_manager_cron() {
58    
59      // if don't run this site's cron jobs      // if don't run this site's cron jobs
60      if (!$node->run_cron) {      if (!$node->run_cron) {
61        watchdog('cron', t('Skipping cron for %title.', array('%title' => $node->title)));        watchdog('cron', 'Skipping cron for %title.', array('%title' => $node->title));
62      }      }
63      // if run this site's cron jobs      // if run this site's cron jobs
64      else {      else {
# Line 72  function multisite_manager_cron() { Line 77  function multisite_manager_cron() {
77         * like update, etc might be possible.         * like update, etc might be possible.
78         */         */
79    
80        watchdog('cron', t('Running cron for %title at "%url".', array('%title' => $node->title, '%url' => $node_cron_url)));        watchdog('cron', 'Running cron for %title at "%url".', array('%title' => $node->title, '%url' => $node_cron_url));
81        $result = drupal_http_request($node_cron_url);        $result = drupal_http_request($node_cron_url);
82    
83        if ($result->error) {        if ($result->error) {
# Line 82  function multisite_manager_cron() { Line 87  function multisite_manager_cron() {
87                             '%url' => $node_cron_url,                             '%url' => $node_cron_url,
88                             ));                             ));
89          drupal_set_message($message,'error');          drupal_set_message($message,'error');
90          watchdog('cron',$message, WATCHDOG_WARNING);          watchdog('cron',$message, array(), WATCHDOG_WARNING);
91        } // end if error        } // end if error
92      }      }
93    } // end while nodes    } // end while nodes
# Line 116  function multisite_manager_view($node, $ Line 121  function multisite_manager_view($node, $
121  /**  /**
122   * Implementation of hook_menu().   * Implementation of hook_menu().
123   */   */
124  function multisite_manager_menu($may_cache) {  function multisite_manager_menu() {
125    $items = array();    $items = array();
126    if ($may_cache) {    $items['admin/settings/multisite_manager'] = array(
127      $items[] = array('path' => 'admin/settings/multisite_manager',      'title' => t('Multisite Manager settings'),
128        'title' => t('Multisite Manager settings'),      'page callback' => 'drupal_get_form',
129        'description' => t('Configure the database and url defaults for new sites.'),      'page arguments' => array('multisite_manager_admin_settings'),
130        'callback' => 'drupal_get_form',      'access arguments' => array('administer multisite defaults'),
131        'callback arguments' => array('multisite_manager_admin_settings'),      );
132        'access' => user_access('administer multisite defaults'),    $items['admin/settings/multisite_manager/defaults'] = array(
133        'type' => MENU_NORMAL_ITEM);      'title' => t('Defaults'),
134        'description' => t('Configure the database and url defaults for new sites.'),
135    }      'page callback' => 'drupal_get_form',
136        'page arguments' => array('multisite_manager_admin_settings'),
137        'access arguments' => array('administer multisite defaults'),
138        'type' => MENU_DEFAULT_LOCAL_TASK,
139        );
140      $items['admin/settings/multisite_manager/phpsettingfile'] = array(
141        'title' => t('settings.php help'),
142        'type' => MENU_LOCAL_TASK,
143        'description' => t('What to put in the settings.php file'),
144        'page callback' => 'multisite_manager_admin_file_settingsdotphp',
145        'access arguments' => array('administer multisite defaults')
146        );
147    return $items;    return $items;
148  }  }
149    
# Line 451  function _multisite_manager_db_error_mes Line 467  function _multisite_manager_db_error_mes
467      case 'mysql':      case 'mysql':
468        return mysql_error();        return mysql_error();
469      case 'mysqli':      case 'mysqli':
470        return mysqli_error();        return mysqli_error(db_set_active());
471      case 'pgsql':      case 'pgsql':
472        return pg_last_error();        return pg_last_error();
473    }    }
# Line 517  function _multisite_manager_newdb($new_d Line 533  function _multisite_manager_newdb($new_d
533        drupal_set_message("Database already existed");        drupal_set_message("Database already existed");
534      }      }
535      elseif ($errors) {      elseif ($errors) {
536        drupal_set_message("Database error when creating database: $error", 'error');        //what's 1004: access denied!
537          //needs GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX,                 ALTER, CREATE TEMPORARY TABLES, LOCK TABLES  on *.* to 'drupaluser'@'localhost' identified by '*****' with grant option;
538          drupal_set_message("Database error when creating database: $errors", 'error');
539        return FALSE;        return FALSE;
540      }      }
541    }    }
# Line 578  function multisite_manager_insert($node) Line 596  function multisite_manager_insert($node)
596    
597  function multisite_manager_install_site($node) {  function multisite_manager_install_site($node) {
598    /**    /**
599       *
600     *  1. If it's a different database and/or user from the current     *  1. If it's a different database and/or user from the current
601     *     then creates them (assumes db access to do so)     *     then creates them (assumes db access to do so)
602     *  2. switches to the new context (db,user,table prefix)     *  2. switches to the new context (db,user,table prefix)
603     *  3. installs drupal profile in new place     *  3. installs drupal profile in new place
604     *  4. switches back to current context     *  4. switches back to current context
605     */     */
606    global $multisite_manager_installmodules, $db_prefix, $conf;    global $multisite_manager_installmodules, $db_prefix, $conf, $locale, $user;
607    
608      if (!$multisite_manager_installmodules) {
609        ///if this function is run by a script, then _validate() won't have
610        /// been called
611        $multisite_manager_installmodules = drupal_verify_profile($node->profile, $locale);
612        if (!$multisite_manager_installmodules) {
613          echo "\n" . t("One or more required modules are missing!") . "\n";
614          exit();
615        }
616      }
617    
618      ///get user for admin account
619      $admin_how = variable_get('multisite_manager_admin_account', 'copy creator');
620      switch($admin_how) {
621      case 'copy admin':
622        $account = user_load(1);
623        break;
624      case 'copy creator':
625        $account = $user;
626      }
627    
628      #$multisite_manager_installmodules = drupal_verify_profile($node->profile, $locale);
629    include_once './includes/install.inc';    include_once './includes/install.inc';
630      //
631    
632    /**    /**
633     * creates database and user w/ permissions if necessary     * creates database and user w/ permissions if necessary
# Line 615  function multisite_manager_install_site( Line 656  function multisite_manager_install_site(
656    $cur_conf = $conf; //should be an array copy here    $cur_conf = $conf; //should be an array copy here
657    $conf = array();    $conf = array();
658    
659    drupal_install_profile($node->profile, $multisite_manager_installmodules);    ///THEFT (install.php)
660      drupal_install_system();
661      #variable_set('install_profile_modules', array_diff($multisite_manager_installmodules, array('system')));
662    
663      #install_tasks($node->profile, $task); //can't use this
664    
665      ///THEFT (install.php)
666      drupal_install_modules($multisite_manager_installmodules);
667    
668      /*BEGIN THEFT*/
669      //TODO: install locale stuff
670      /*END THEFT (install.php) */
671    
672      ///TASK 'configure' (admin account)
673      if ($admin_how !== 'do nothing') {
674        ///THEFT (install.php)
675        $newsite_account = user_load(1);
676        user_save($newsite_account, array('name' => $account->name,
677                                          'mail' => $account->mail,
678                                          'roles' => array(),
679                                          'status' => 1,
680                                          ) );
681        //no save password raw function :-(
682        $success = db_query("UPDATE {users} SET pass = '%s' WHERE uid = 1", array($account->pass));
683      }
684    
685    
686    //after install_profile, because otherwise {cache} and {variable} don't exist yet    //after install_profile, because otherwise {cache} and {variable} don't exist yet
687    variable_init(); //soak up anything from {variable}    variable_init(); //soak up anything from {variable}
688    
689    /* code ripped from install.php:install_complete  */    /*BEGIN THEFT*/
690    // Store install profile for later use.    //TODO: call profile tasks
   variable_set('install_profile', $node->profile);  
691    
692    // Show profile finalization info.    // Show profile finalization info.
693    $function = $node->profile.'_profile_final';    $function = $node->profile.'_profile_tasks';
694    if (function_exists($function)) {    if (function_exists($function)) {
695      // More steps required      // More steps required
696      //PARANOIA: buggy set_active_db() makes us set this again, just for fun      //PARANOIA: buggy set_active_db() makes us set this again, just for fun
697      /*END THEFT*/
698    
699      $mid_cur_db = _multisite_manager_dbswitch($new_db);      $mid_cur_db = _multisite_manager_dbswitch($new_db);
700      $profile_message = $function();      //BUG: $url here will probably mess things up if it's actually used
701    }      $task = 'profile'; ///is passed by reference. we should foreach the tasks
702        $profile_message = $function($task, _multisite_manager_node_url($node));
703      }
704    
705      //PARANOIA: buggy set_active_db() makes us set this again, just for fun
706      $mid_cur_db = _multisite_manager_dbswitch($new_db);
707    
708      ///TASK 'done'
709      /*BEGIN THEFT (install.php)*/
710      /* code ripped from install.php:install_tasks  */
711    
712      // Rebuild menu to get content type links registered by the profile,
713      // and possibly any other menu items created through the tasks.
714      menu_rebuild();
715      actions_synchronize();
716      // Store install profile for later use.
717      variable_set('install_profile', $node->profile);
718      /*END THEFT (install.php)*/
719    
720    if ($new_db['new'] && $new_db['prefix'] != $db_prefix) {    if ($new_db['new'] && $new_db['prefix'] != $db_prefix) {
721      ///OK, time to rename all the tables that were just created      ///OK, time to rename all the tables that were just created
# Line 649  function multisite_manager_install_site( Line 733  function multisite_manager_install_site(
733        drupal_set_message('Something has gone horribly wrong.  The database '. $mid_cur_db['url']  .' is NOT the new one.  Therefore, the database was switched mysteriously some time during installation.  Thus some features that were intended to be in your new database may have polluted your current database.','error');        drupal_set_message('Something has gone horribly wrong.  The database '. $mid_cur_db['url']  .' is NOT the new one.  Therefore, the database was switched mysteriously some time during installation.  Thus some features that were intended to be in your new database may have polluted your current database.','error');
734      }      }
735    
     ///special duty for {sequences} until it doesn't buggily store the prefix; BUG: http://drupal.org/node/168977  
     ///do this BEFORE table rename or we'll have to muck with the db_prefix.  
     if (db_table_exists('sequences')) {  
       @db_query("UPDATE {sequences} SET name = INSERT(name,1,%d,'%s')", strlen($cur_db['prefix']), $new_db['prefix']);  
     }  
   
736      ///Actually RENAME the TABLES      ///Actually RENAME the TABLES
737      while($table = @db_fetch_array($result)) {      while($table = @db_fetch_array($result)) {
738        $table_name = array_pop($table);        $table_name = array_pop($table);
# Line 678  function multisite_manager_install_site( Line 756  function multisite_manager_install_site(
756    if (isset($profile_message)) {    if (isset($profile_message)) {
757      drupal_set_message($profile_message);      drupal_set_message($profile_message);
758    }    }
759    
760  }  }
761    
762  /**  /**
# Line 783  function multisite_manager_admin_setting Line 862  function multisite_manager_admin_setting
862    }    }
863  }  }
864    
865    /*
866     * multisite_manager_admin_file_settingsdotphp
867     * @return string of PHP code that would be included based on the default settings for link/database name
868     */
869    function multisite_manager_admin_file_settingsdotphp() {
870      global $base_url;
871      $link = variable_get('multisite_manager_link_default', '');
872      ///
873      $fakenode = new stdClass();
874      $fakenode->shortname = '". $my_site_base ."';
875      $fakenode->db_prefix = variable_get('multisite_manager_dbprefix_default', '');
876      $fakenode->db_user = '';
877      $fakenode->db_pass = '<b style="color:red">DATABASE_PASSWORD</b>';
878      $fakenode->db_path = variable_get('multisite_manager_dbpath_default', '');
879      $newdb = _multisite_manager_dbobj($fakenode);
880    
881      $recommended_directory = '';
882    
883      if (!$link || !$fakenode->db_path) {
884        return "ERROR: no link or db url";
885      }
886      $link = str_replace('{base_url}', $base_url, $link);
887    
888      //$url_pieces[2] is hostname, $url_pieces[3] is path
889      $url_pieces = explode('/', $link, 4);
890    
891      $rv = array('<p>Based on your configuration in '.l( 'Multisite Manager Defaults','admin/settings/multisite_manager/defaults').' The following code should be added to a special settings.php file which .  Note, <b>This is an experimental feature</b> and you should look over this carefully before adding it in place of the database configuration (Also, please '.l('report suggestions/issues','http://drupal.org/project/multisite_manager') .').</p><blockquote><pre><code>',
892                  '$matches = FALSE;');
893    
894      $host_regex = str_replace('{shortname}', '(\w+)', $url_pieces[2]);
895      $path_regex = str_replace('{shortname}', '(\w+)', $url_pieces[3]);
896    
897      //assumes shortname will never be the TLD
898      $recommended_directory = preg_replace('|\(\\w\+\)[^.]*\.|','',$host_regex);
899      ///shortname in hostname
900      if (strpos($url_pieces[2],'{shortname}') !== FALSE) {
901        $rv[] = 'if (preg_match("|'. $host_regex .'|",$_SERVER["HTTP_HOST"], $matches)';
902        $rv[] = '    && preg_match("|'. $path_regex .'|",request_uri())';
903        $rv[] = '    && $matches)';
904        $rv[] = '{';
905      }///shortname in path
906      elseif (strpos($url_pieces[3],'{shortname}') !== FALSE) {
907        $rv[] = 'if (preg_match("|'. $host_regex .'|",$_SERVER["HTTP_HOST"])';
908        $rv[] = '    && preg_match("|'. $path_regex .'|",request_uri(), $matches)';
909        $rv[] = '    && $matches)';
910        $rv[] = '{';
911        $recommended_directory .= '.' . str_replace('/','.',preg_replace('|(/[^/]*)?\(\\\w\+\)([^/]*)|','',$path_regex));
912      }
913      else {
914        ///{shortname} has to appear in the link somewhere!
915        return "ERROR: shortname must be in the link template " .$url_pieces[2] .'XX' . $url_pieces[3];
916      }
917      $rv[] = '  $my_site_base = $matches[1];';
918    
919      ///prefix
920      $rv[] = '  $db_prefix = "' . $newdb['prefix'] .'";';
921      ///needs URL structure
922      $rv[] = '  $base_url = "'. str_replace('{shortname}','". $my_site_base ."',$link) .'";  // NO trailing slash!';
923    
924      ///needs newDB URI structure
925      $rv[] = '  $db_url = "' .$newdb['url'] .'";';
926    
927      $rv[] = '  ///This assumes you have a ./files directory in your base drupal directory';
928      $rv[] = '  $conf = array(';
929      $rv[] = '     "file_directory_path" => "files/".$my_site_base,';
930      $rv[] = '  );';
931      $rv[] = '}';
932    
933      $rv[] = "</code></pre></blockquote>";
934      $rv[] = 'Suggested directory under sites/ to include settings.php file: <b>' . $recommended_directory . "</b></p>";
935      return implode("\n",$rv);
936    }
937    
938  function multisite_manager_admin_settings() {  function multisite_manager_admin_settings() {
939    $defaults = array('db_prefix' => '{shortname}_',    $defaults = array('db_prefix' => '{shortname}_',
940                      'db_path' => '',                      'db_path' => '',
941                      'link' => '{base_url}/site/{shortname}',                      'link' => '{base_url}/site/{shortname}',
942                        'admin_account' => 'copy creator',
943                      'profile' => 'default',                      'profile' => 'default',
944                      'install_immediate' => TRUE,                      'install_immediate' => TRUE,
945                      'run_cron' => 0,                      'run_cron' => 0,
# Line 826  function multisite_manager_admin_setting Line 979  function multisite_manager_admin_setting
979      '#default_value' => variable_get('multisite_manager_link_default', $defaults['link']),      '#default_value' => variable_get('multisite_manager_link_default', $defaults['link']),
980      '#description' => t('This is where the site will be accessible by default.  If you setup your ./sites/default/settings.php correctly along with your web server (e.g. apache/htaccess) config, you can anticipate where the new site will live and forward the user to the new site location upon creation.  Here, there are two dynamic variables, {base_url} and {shortname}.')      '#description' => t('This is where the site will be accessible by default.  If you setup your ./sites/default/settings.php correctly along with your web server (e.g. apache/htaccess) config, you can anticipate where the new site will live and forward the user to the new site location upon creation.  Here, there are two dynamic variables, {base_url} and {shortname}.')
981    );    );
982      $form['multisite_manager_admin_account'] = array(
983        '#type' => 'radios',
984        '#title' => t('Admin account on new sites'),
985        '#required' => TRUE,
986        '#options' => array(
987                            'copy admin' => t('Copy the admin account from this site'),
988                            'copy creator' => t('Copy the account of the creator'),
989                            'do nothing' => t('Do nothing (only choose this if all profiles available do something instead.  the default profile does not)'),
990                            /*'prompt creator' => '',*/
991                            ),
992        '#default_value' => variable_get('multisite_manager_admin_account', $defaults['admin_account']),
993      );
994    $form['multisite_manager_profile_default'] = array(    $form['multisite_manager_profile_default'] = array(
995      '#type' => 'radios',      '#type' => 'radios',
996      '#title' => t('Profile default'),      '#title' => t('Profile default'),
# Line 854  function _multisite_manager_node_url($no Line 1019  function _multisite_manager_node_url($no
1019  } // end function _multisite_manager_node_url()  } // end function _multisite_manager_node_url()
1020    
1021    
1022    function multisite_manager_theme() {
1023      return array('multisite_manager_sitelink' => array ('arguments'=>array('node')));
1024    }
1025    
1026  function theme_multisite_manager_sitelink($node) {  function theme_multisite_manager_sitelink($node) {
1027    return l($node->title .' '. t('Site'), $node->url);    return l($node->title .' '. t('Site'), $node->url);
1028  }  }

Legend:
Removed from v.1.8  
changed lines
  Added in v.1.8.4.1

  ViewVC Help
Powered by ViewVC 1.1.2