Commit 5d759ccb authored by Dries's avatar Dries

- Patch #5942 by jhriggs and Adrian:

    + added support for multi-site configurations.
    + tidied up some old cruft and added code comments.
parent 062a8abd
......@@ -14,6 +14,8 @@ Drupal x.x.x, xxxx-xx-xx
- usability:
* refactored the throttle module configuration.
* added a 'add child page' link to book pages.
- multi-site configuration:
* made it possible to run multiple sites from a single code base.
- performance:
* improved performance of the forum topics block.
* improved performance of the tracker module.
......
......@@ -103,15 +103,8 @@ INSTALLATION
4. CONNECTING DRUPAL
Drupal server options are specified in includes/conf.php.
Drupal allows for multiple virtual host installations; to configure
a virtual server host, you can create the configuration file
includes/www.example.com.php
where www.example.com is your website's URL.
The default configuration can be found in the
'sites/default/settings.php' file within your Drupal installation.
Before you can run Drupal, you must set the database URL and the
base URL to the web site. Open the configuration file and edit the
$db_url line to match the database defined in the previous steps:
......@@ -122,6 +115,61 @@ INSTALLATION
$base_url = "http://www.example.com";
In addition, a single Drupal installation can host several
Drupal-powered sites, each with its own individual configuration.
If you don't need to run multiple Drupal sites, you can skip to the
next section.
Additional site configurations are created in subdirectories within
the 'sites' directory. Each site subdirectory must have a
'settings.php' file which specifies the configuration settings. The
easiest way to create additional sites is to copy the 'default'
directory and modify the 'settings.php' file as appropriate. The new
directory name is constructed from the site's URL. The
configuration for www.example.com could be in
'sites/example.com/settings.php' (note that 'www.' should be omitted
if users can access your site at http://example.com/).
Sites do not each have to have a different domain. You can use
subdomains and subdirectories for Drupal sites also. For example,
example.com, sub.example.com, and sub.example.com/site3 can all be
defined as independent Drupal sites. The setup for a configuration
such as this would look like the following:
sites/default/settings.php
sites/example.com/settings.php
sites/sub.example.com/settings.php
sites/sub.example.com.site3/settings.php
When searching for a site configuration (for example
www.sub.example.com/site3), Drupal will search for configuration
files in the following order, using the first configuration file it
finds:
sites/www.sub.example.com.site3/settings.php
sites/sub.example.com.site3/settings.php
sites/example.com.site3/settings.php
sites/www.sub.example.com/settings.php
sites/sub.example.com/settings.php
sites/example.com/settings.php
sites/default/settings.php
Each site configuration can have its own site-specific modules and
themes that will be made available in addition to those installed
in the standard 'modules' and 'themes' directories. To use
site-specific modules or themes, simply create a 'modules' or
'themes' directory within the site configuration directory. For
example, if sub.example.dom has a custom theme and a custom module
that should not be accessible to other sites, the setup would look
like this:
sites/sub.example.com/:
settings.php
themes/:
custom_theme
modules/:
custom_module
NOTE: for more information about multiple virtual hosts or the
configuration settings, consult the Drupal handbook at drupal.org.
......
......@@ -767,11 +767,15 @@ CREATE TABLE watchdog (
INSERT INTO system VALUES ('modules/admin.module','admin','module','',1,0,0);
INSERT INTO system VALUES ('modules/block.module','block','module','',1,0,0);
INSERT INTO system VALUES ('modules/comment.module','comment','module','',1,0,0);
INSERT INTO system VALUES ('modules/filter.module','filter','module','',1,0,0);
INSERT INTO system VALUES ('modules/help.module','help','module','',1,0,0);
INSERT INTO system VALUES ('modules/node.module','node','module','',1,0,0);
INSERT INTO system VALUES ('modules/page.module','page','module','',1,0,0);
INSERT INTO system VALUES ('modules/story.module','story','module','',1,0,0);
INSERT INTO system VALUES ('modules/system.module','system','module','',1,0,0);
INSERT INTO system VALUES ('modules/taxonomy.module','taxonomy','module','',1,0,0);
INSERT INTO system VALUES ('modules/user.module','user','module','',1,0,0);
INSERT INTO system VALUES ('modules/watchdog.module','watchdog','module','',1,0,0);
INSERT INTO system VALUES ('themes/bluemarine/xtemplate.xtmpl','bluemarine','theme','themes/engines/xtemplate/xtemplate.engine',1,0,0);
INSERT INTO system VALUES ('themes/engines/xtemplate/xtemplate.engine','xtemplate','theme_engine','',1,0,0);
INSERT INTO users (uid, name, mail) VALUES ('0', '', '');
......
......@@ -751,11 +751,15 @@ CREATE TABLE watchdog (
INSERT INTO system VALUES ('modules/admin.module','admin','module','',1,0,0);
INSERT INTO system VALUES ('modules/block.module','block','module','',1,0,0);
INSERT INTO system VALUES ('modules/comment.module','comment','module','',1,0,0);
INSERT INTO system VALUES ('modules/filter.module','filter','module','',1,0,0);
INSERT INTO system VALUES ('modules/help.module','help','module','',1,0,0);
INSERT INTO system VALUES ('modules/node.module','node','module','',1,0,0);
INSERT INTO system VALUES ('modules/page.module','page','module','',1,0,0);
INSERT INTO system VALUES ('modules/story.module','story','module','',1,0,0);
INSERT INTO system VALUES ('modules/system.module','system','module','',1,0,0);
INSERT INTO system VALUES ('modules/taxonomy.module','taxonomy','module','',1,0,0);
INSERT INTO system VALUES ('modules/user.module','user','module','',1,0,0);
INSERT INTO system VALUES ('modules/watchdog.module','watchdog','module','',1,0,0);
INSERT INTO system VALUES ('themes/bluemarine/xtemplate.xtmpl','bluemarine','theme','themes/engines/xtemplate/xtemplate.engine',1,0,0);
INSERT INTO system VALUES ('themes/engines/xtemplate/xtemplate.engine','xtemplate','theme_engine','',1,0,0);
......
......@@ -12,25 +12,41 @@
/**
* Locate the appropriate configuration file.
*
* Try finding a matching configuration file by stripping the website's
* URI from left to right. If no configuration file is found, return the
* default value, "conf".
* Try finding a matching configuration directory by stripping the
* website's hostname from left to right and pathname from right to
* left. If no configuration file is found, return a default value
* '$confdir/default'. Example for a ficticious site installed at
* http://www.drupal.org/test:
*
* 1. www.drupal.org.test
* 2. drupal.org.test
* 3. www.drupal.org
* 4. drupal.org
* 5. default
*/
function conf_init() {
$uri = $_SERVER['PHP_SELF'];
static $conf = '';
$file = strtolower(strtr($_SERVER['HTTP_HOST'] . substr($uri, 0, strrpos($uri, '/')), '/:', '..'));
if ($conf) {
return $conf;
}
while (strlen($file) > 4) {
if (file_exists('includes/'. $file .'.php')) {
return $file;
}
else {
$file = substr($file, strpos($file, '.') + 1);
$uri = explode('/', $_SERVER['PHP_SELF']);
$server = explode('.', $_SERVER['HTTP_HOST']);
$confdir = 'sites';
for ($i = count($uri) - 1; $i > 0; $i--) {
for ($j = count($server); $j > 0; $j--) {
$dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i));
if (file_exists("$confdir/$dir/settings.php")) {
$conf = "$confdir/$dir";
return $conf;
}
}
}
return 'conf';
print "$confdir/default/settings.php<br />";
$conf = "$confdir/default";
return $conf;
}
/**
......@@ -442,7 +458,7 @@ function drupal_get_messages() {
unset($conf);
$config = conf_init();
include_once "includes/$config.php";
include_once "$config/settings.php";
include_once 'includes/database.inc';
include_once 'includes/session.inc';
include_once 'includes/module.inc';
......
......@@ -1836,6 +1836,100 @@ function drupal_eval($code) {
return $output;
}
/**
* Returns and optionally sets the filename for a system item (module,
* theme, etc.). The filename, whether provided, cached, or retrieved
* from the database, is only returned if the file exists.
*
* @param $type
* The type of the item (i.e. theme, theme_engine, module).
* @param $name
* The name of the item for which the filename is requested.
* @param $filename
* The filename of the item if it is to be set explicitly rather
* than by consulting the database.
*
* @return
* The filename of the requested item.
*/
function drupal_get_filename($type, $name, $filename = NULL) {
static $files = array();
if (!$files[$type]) {
$files[$type] = array();
}
if ($filename && file_exists($filename)) {
$files[$type][$name] = $filename;
}
elseif ($files[$type][$name]) {
// nothing
}
elseif (($file = db_result(db_query("SELECT filename FROM {system} WHERE name = '%s' AND type = '%s'", $name, $type))) && file_exists($file)) {
$files[$type][$name] = $file;
}
else {
$config = conf_init();
$dir = (($type == 'theme_engine') ? 'themes/engines' : "${type}s");
$file = "$name.$type";
foreach (array("$config/$dir/$file", "$config/$dir/$name/$file", "$dir/$file", "$dir/$name/$file") as $file) {
if (file_exists($file)) {
$files[$type][$name] = $file;
break;
}
}
}
return $files[$type][$name];
}
/**
* Returns the path to a system item (module, theme, etc.).
*
* @param $type
* The type of the item (i.e. theme, theme_engine, module).
* @param $name
* The name of the item for which the path is requested.
*
* @return
* The path to the requested item.
*/
function drupal_get_path($type, $name) {
return dirname(drupal_get_filename($type, $name));
}
/**
* Includes a file with the provided type and name. This prevents
* including a theme, engine, module, etc., more than once.
*
* @param $type
* The type of item to load (i.e. theme, theme_engine, module).
* @param $name
* The name of the item to load.
*
* @return
* TRUE if the item is loaded or has already been loaded.
*/
function drupal_load($type, $name) {
static $files = array();
if ($files[$type][$name]) {
return TRUE;
}
$filename = drupal_get_filename($type, $name);
if ($filename) {
include_once($filename);
$files[$type][$name] = TRUE;
return TRUE;
}
return FALSE;
}
include_once 'includes/theme.inc';
include_once 'includes/pager.inc';
include_once 'includes/menu.inc';
......
......@@ -469,39 +469,59 @@ function file_download() {
}
/**
* Finds all files that match a given mask in a given directory.
* Finds all files that match a given mask in a given
* directory.
*
* @param $dir Directory to scan
* @param $mask Regular expression to filter out files. Only filenames that
* match the mask will be returned.
* @param $nomask Array of filenames which should never be returned regardless
* if they match the $mask
* @param $callback Function to call for qualifying file.
* Set to 0 or false if you do not want callbacks.
* @param $recurse When true directory scan will recurse the entire tree starting at $dir
* @return Array of qualifying files
* @param $dir
* The base directory for the scan.
* @param $mask
* The regular expression of the files to find.
* @param $nomask
* An array of files/directories to ignore.
* @param $callback
* The callback function to call for each match.
* @param $recurse
* When TRUE, the directory scan will recurse the entire tree
* starting at the provided directory.
* @param $key
* The key to be used for the returned array of files. Possible
* values are "filename", for the path starting with $dir,
* "basename", for the basename of the file, and "name" for the name
* of the file without an extension.
*
* @return
* An associative array (keyed on the provided key) of objects with
* "path", "basename", and "name" members corresponding to the
* matching files.
*/
function file_scan_directory($dir, $mask, $nomask = array('.', '..', 'CVS'), $callback = 0, $recurse = TRUE) {
function file_scan_directory($dir, $mask, $nomask = array('.', '..', 'CVS'), $callback = 0, $recurse = TRUE, $key = 'filename') {
$key = (in_array($key, array('filename', 'basename', 'name')) ? $key : 'filename');
$files = array();
if (is_dir($dir) && $handle = opendir($dir)) {
while ($file = readdir($handle)) {
if (!in_array($file, $nomask)) {
if (is_dir("$dir/$file") && $recurse) {
$files = array_merge($files, file_scan_directory("$dir/$file", $mask, $nomask, $callback));
$files = array_merge($files, file_scan_directory("$dir/$file", $mask, $nomask, $callback, $recurse, $key));
}
elseif (ereg($mask, $file)) {
$name = basename($file);
$files["$dir/$file"] = new stdClass();
$files["$dir/$file"]->filename = "$dir/$file";
$files["$dir/$file"]->name = substr($name, 0, strrpos($name, '.'));
$filename = "$dir/$file";
$basename = basename($file);
$name = substr($basename, 0, strrpos($basename, '.'));
$files[$$key] = new stdClass();
$files[$$key]->filename = $filename;
$files[$$key]->basename = $basename;
$files[$$key]->name = $name;
if ($callback) {
$callback("$dir/$file");
$callback($filename);
}
}
}
}
closedir($handle);
}
return $files;
}
......
......@@ -61,8 +61,8 @@ function module_list($refresh = FALSE, $bootstrap = FALSE) {
// variables, since throttle.module may not be loaded yet.
$throttle = ($module->throttle && variable_get('throttle_level', 0) > 0);
if (!$throttle) {
drupal_get_filename('module', $module->name, $module->filename);
$list[$module->name] = $module->name;
module_set_filename($module->name, $module->filename);
}
}
}
......@@ -71,86 +71,20 @@ function module_list($refresh = FALSE, $bootstrap = FALSE) {
return $list;
}
/**
* Set the filename of a module, for future loading through module_load()
*
* @param $module
* Name of the module which to specify the filename of.
* @param $pa
* Filename of the module named $module.
* @return
* Filename of module, if no $path has been specified.
*/
function module_set_filename($module, $path = null) {
static $list;
if ($path) {
$list[$module] = $path;
}
else {
return $list[$module] ? $list[$module] : "modules/$module.module";
}
}
/**
* Retrieve the filename of a module
*
* @param $module
* Name of the module which to retrieve the filename of.
* @return
* Filename of module.
*/
function module_get_filename($module) {
return module_set_filename($module);
}
/**
* Retrieve the path of a module
*
* @param $module
* Name of the module which to retrieve the path of.
* @return
* Path of module.
*/
function module_get_path($module) {
return dirname(module_get_filename($module));
}
/**
* Load a module into Drupal, but check first whether a module by the same name
* has been loaded, and that the filename being included exists.
* @param $module
* The name of the module to be loaded.
* @return
* TRUE if the load was successful.
*/
function module_load($module) {
static $loaded = array();
if (!$loaded[$module]) {
$filename = module_get_filename($module);
if (file_exists($filename)) {
include_once($filename);
$loaded[$module] = $filename;
return true;
}
}
return false;
}
/**
* Load all the modules that have been enabled in the system table.
*
* @return
* TRUE if all modules were loaded successfully
* TRUE if all modules were loaded successfully.
*/
function module_load_all() {
$list = module_list();
$status = true;
$status = TRUE;
foreach ($list as $module) {
$status &= module_load($module);
$status = (drupal_load('module', $module) && $status);
}
return $status;
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -10,15 +10,15 @@
function xtemplate_init($template) {
// We cannot use the theme() or path_to_theme() functions here
if (!class_exists('XTemplate')) {
include_once('themes/engines/xtemplate/xtemplate.inc');
include_once(dirname(__FILE__) . '/xtemplate.inc');
}
$GLOBALS["xtemplate"] = new StdClass();
$GLOBALS['xtemplate']->template = new XTemplate(basename($template->filename), dirname($template->filename));
$GLOBALS['xtemplate']->template->SetNullBlock(' '); // '' doesn't work!
}
function xtemplate_templates($directory) {
return file_scan_directory($directory, 'xtemplate.xtmpl$');
function xtemplate_templates() {
return system_listing('^xtemplate\.xtmpl$', 'themes', 'filename');
}
function xtemplate_features() {
......
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