aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engine/settings.example.php98
-rw-r--r--engine/start.php153
-rw-r--r--htaccess_dist3
-rw-r--r--install.php35
-rw-r--r--install/ElggInstaller.php1274
-rw-r--r--install/install.css266
-rw-r--r--languages/en.php101
-rw-r--r--views/failsafe/input/password.php23
-rw-r--r--views/failsafe/install/footer.php10
-rw-r--r--views/failsafe/install/forms/admin.php21
-rw-r--r--views/failsafe/install/forms/database.php20
-rw-r--r--views/failsafe/install/forms/settings.php20
-rw-r--r--views/failsafe/install/forms/template.php27
-rw-r--r--views/failsafe/install/header.php6
-rw-r--r--views/failsafe/install/nav.php35
-rw-r--r--views/failsafe/install/pages/admin.php8
-rw-r--r--views/failsafe/install/pages/complete.php14
-rw-r--r--views/failsafe/install/pages/database.php16
-rw-r--r--views/failsafe/install/pages/requirements.php39
-rw-r--r--views/failsafe/install/pages/settings.php5
-rw-r--r--views/failsafe/install/pages/welcome.php8
-rw-r--r--views/failsafe/install/sidebar.php26
-rw-r--r--views/failsafe/page_shells/install.php51
23 files changed, 2051 insertions, 208 deletions
diff --git a/engine/settings.example.php b/engine/settings.example.php
index 4f47872cb..aa50be6bc 100644
--- a/engine/settings.example.php
+++ b/engine/settings.example.php
@@ -29,105 +29,24 @@ if (!isset($CONFIG)) {
* to explain, but if you know you need it, skip past this section.
*/
-/**
- * The database username
- *
- * @global string $CONFIG->dbuser
- * @name $CONFIG->dbuser
- */
-$CONFIG->dbuser = '{{CONFIG_DBUSER}}';
-
-/**
- * The database password
- *
- * @global string $CONFIG->dbpass
- */
-$CONFIG->dbpass = '{{CONFIG_DBPASS}}';
-
-/**
- * The database name
- *
- * @global string $CONFIG->dbname
- */
-$CONFIG->dbname = '{{CONFIG_DBNAME}}';
-
-/**
- * The database host.
- *
- * For most installations, this is 'localhost'
- *
- * @global string $CONFIG->dbhost
- */
-$CONFIG->dbhost = '{{CONFIG_DBHOST}}';
-
-/**
- * The database prefix
- *
- * This prefix will be appended to all Elgg tables. If you're sharing
- * a database with other applications, use a database prefix to namespace tables
- * in order to avoid table name collisions.
- *
- * @global string $CONFIG->dbprefix
- */
-$CONFIG->dbprefix = '{{CONFIG_DBPREFIX}}';
-
-/**
- * Multiple database connections
- *
- * Here you can set up multiple connections for reads and writes. To do this, uncomment out
- * the lines below.
- *
- * @todo Does this work?
- */
-
-/*
-
-// Yes! We want to split reads and writes
-$CONFIG->db->split = true;
-
-// READS
-// Database username
-$CONFIG->db['read']->dbuser = "";
-
-// Database password
-$CONFIG->db['read']->dbpass = "";
-
-// Database name
-$CONFIG->db['read']->dbname = "";
-
-// Database server
-// (For most configurations, you can leave this as 'localhost')
-$CONFIG->db['read']->dbhost = "localhost";
-
-// WRITES
// Database username
-$CONFIG->db['write']->dbuser = "";
+$CONFIG->dbuser = '{{dbuser}}';
// Database password
-$CONFIG->db['write']->dbpass = "";
+$CONFIG->dbpass = '{{dbpassword}}';
// Database name
-$CONFIG->db['write']->dbname = "";
+$CONFIG->dbname = '{{dbname}}';
// Database server
// (For most configurations, you can leave this as 'localhost')
-$CONFIG->db['write']->dbhost = "localhost";
+$CONFIG->dbhost = '{{dbhost}}';
- */
-
-/*
- * For extra connections for both reads and writes, you can turn both
- * $CONFIG->db['read'] and $CONFIG->db['write'] into an array, eg:
- *
- * $CONFIG->db['read'][0]->dbhost = "localhost";
- *
- * Note that the array keys must be numeric and consecutive, i.e., they start
- * at 0, the next one must be at 1, etc.
- */
+// Database table prefix
+// If you're sharing a database with other applications, you will want to use this
+// to differentiate Elgg's tables.
+$CONFIG->dbprefix = '{{dbprefix}}';
-/*
- * Optional configuration
- */
/**
* Memcache setup (optional)
@@ -146,6 +65,7 @@ $CONFIG->db['write']->dbhost = "localhost";
// array('server2', 11211)
//);
+
/**
* Use non-standard headers for broken MTAs.
*
diff --git a/engine/start.php b/engine/start.php
index d9ec01b87..db9bff0e4 100644
--- a/engine/start.php
+++ b/engine/start.php
@@ -11,19 +11,19 @@
* If Elgg is uninstalled, the browser will be redirected to an
* installation page.
*
- * If in an installation, attempts to save the .htaccess and
- * settings.php files during {@link sanitised()}
- *
- * @warning The view type is set to 'failsafe' during boot. This means calling
- * {@link elgg_get_viewtype()} will return 'failsafe' in any function called by
- * the events listed above regardless of actual view. The original view is restored
- * after booting.
- *
* @see install.php
* @package Elgg.Core
* @subpackage Core
*/
+/*
+ * No settings means a fresh install
+ */
+if (!file_exists(dirname(__FILE__) . '/settings.php')) {
+ header("Location: install.php");
+ exit;
+}
+
/**
* The time with microseconds when the Elgg engine was started.
*
@@ -73,110 +73,77 @@ foreach ($required_files as $file) {
}
}
-// Use fallback view until sanitised
-$oldview = get_input('view', 'default');
-set_input('view', 'failsafe');
-
// Register the error handler
set_error_handler('__elgg_php_error_handler');
set_exception_handler('__elgg_php_exception_handler');
-// attempt to save settings.php and .htaccess if in installation.
-if ($sanitised = sanitised()) {
- /**
- * Load the system settings
- */
- if (!include_once(dirname(__FILE__) . "/settings.php")) {
- throw new InstallationException("Elgg could not load the settings file.");
- }
- // Get config
- global $CONFIG;
-
- // load the rest of the library files from engine/lib/
- $lib_files = array(
- // these need to be loaded first.
- 'database.php', 'actions.php',
-
- 'admin.php', 'annotations.php', 'api.php', 'cache.php',
- 'calendar.php', 'configuration.php', 'cron.php', 'entities.php',
- 'export.php', 'extender.php', 'filestore.php', 'group.php',
- 'input.php', 'install.php', 'location.php', 'mb_wrapper.php',
- 'memcache.php', 'metadata.php', 'metastrings.php', 'notification.php',
- 'objects.php', 'opendd.php', 'pagehandler.php',
- 'pageowner.php', 'pam.php', 'plugins.php', 'query.php',
- 'relationships.php', 'river.php', 'sites.php', 'social.php',
- 'statistics.php', 'system_log.php', 'tags.php', 'usersettings.php',
- 'users.php', 'version.php', 'widgets.php', 'xml.php', 'xml-rpc.php'
- );
-
- foreach($lib_files as $file) {
- $file = $lib_dir . $file;
- elgg_log("Loading $file...");
- if (!include_once($file)) {
- throw new InstallationException("Could not load {$file}");
- }
- }
-} else {
- throw new InstallationException(elgg_echo('installation:error:configuration'));
+/**
+ * Load the system settings
+ */
+if (!include_once(dirname(__FILE__) . "/settings.php")) {
+ throw new InstallationException("Elgg could not load the settings file.");
}
-// Autodetect some default configuration settings
-set_default_config();
-
-// Trigger boot events for core. Plugins can't hook
-// into this because they haven't been loaded yet.
-trigger_elgg_event('boot', 'system');
-
-// Check if installed
-$installed = is_installed();
-$db_installed = is_db_installed();
-/**
- * Forward if Elgg is not installed.
- */
-if ((!$installed || !$db_installed)
- && !substr_count($_SERVER["PHP_SELF"], "install.php")
- && !substr_count($_SERVER["PHP_SELF"], "css.php")
- && !substr_count($_SERVER["PHP_SELF"], "action_handler.php")) {
+// load the rest of the library files from engine/lib/
+$lib_files = array(
+ // these need to be loaded first.
+ 'database.php', 'actions.php',
+
+ 'admin.php', 'annotations.php', 'api.php', 'cache.php',
+ 'calendar.php', 'configuration.php', 'cron.php', 'entities.php',
+ 'export.php', 'extender.php', 'filestore.php', 'group.php',
+ 'input.php', 'install.php', 'location.php', 'mb_wrapper.php',
+ 'memcache.php', 'metadata.php', 'metastrings.php', 'notification.php',
+ 'objects.php', 'opendd.php', 'pagehandler.php',
+ 'pageowner.php', 'pam.php', 'plugins.php', 'query.php',
+ 'relationships.php', 'river.php', 'sites.php', 'social.php',
+ 'statistics.php', 'system_log.php', 'tags.php', 'usersettings.php',
+ 'users.php', 'version.php', 'widgets.php', 'xml.php', 'xml-rpc.php'
+);
- header("Location: install.php");
- exit;
+foreach($lib_files as $file) {
+ $file = $lib_dir . $file;
+ elgg_log("Loading $file...");
+ if (!include_once($file)) {
+ throw new InstallationException("Could not load {$file}");
+ }
}
-// Load plugins
-if (($installed) && ($db_installed) && ($sanitised)) {
- load_plugins();
-
- trigger_elgg_event('plugins_boot', 'system');
+// check if the install was completed
+// @todo move into function
+$installed = FALSE;
+try {
+ $installed = is_installed();
+} catch (DatabaseException $e) {}
+if (!$installed) {
+ header("Location: install.php");
+ exit;
}
-// Trigger system init event for plugins
-if (!substr_count($_SERVER["PHP_SELF"], "install.php")
- && !substr_count($_SERVER["PHP_SELF"], "setup.php")) {
+// Autodetect some default configuration settings
+set_default_config();
- trigger_elgg_event('init', 'system');
-}
+// Trigger events
+trigger_elgg_event('boot', 'system');
-// System booted, return to normal view
-if (!elgg_is_valid_view_type($oldview)) {
- if (empty($CONFIG->view)) {
- $oldview = 'default';
- } else {
- $oldview = $CONFIG->view;
- }
-}
+// Load the plugins that are active
+load_plugins();
+trigger_elgg_event('plugins_boot', 'system');
-set_input('view', $oldview);
+// Trigger system init event for plugins
+trigger_elgg_event('init', 'system');
// Regenerate the simple cache if expired.
-// Don't do it on upgrade, because upgrade does it itself.
-if (($installed) && ($db_installed) && !(defined('upgrading') && upgrading == 'upgrading')) {
- $lastupdate = datalist_get("simplecache_lastupdate_$oldview");
- $lastcached = datalist_get("simplecache_lastcached_$oldview");
+// Don't do it on upgrade because upgrade does it itself.
+if (!defined('upgrading')) {
+ $view = get_input('view', 'default');
+ $lastupdate = datalist_get("simplecache_lastupdate_$view");
+ $lastcached = datalist_get("simplecache_lastcached_$view");
if ($lastupdate == 0 || $lastcached < $lastupdate) {
- elgg_view_regenerate_simplecache($oldview);
+ elgg_view_regenerate_simplecache($view);
}
// needs to be set for links in html head
$CONFIG->lastcache = $lastcached;
-} \ No newline at end of file
+}
diff --git a/htaccess_dist b/htaccess_dist
index a2c4dac8b..48129d0f9 100644
--- a/htaccess_dist
+++ b/htaccess_dist
@@ -115,4 +115,7 @@ RewriteRule mt/mt-xmlrpc.cgi engine/handlers/xml-rpc_handler.php
RewriteRule ^tag/(.+)/?$ engine/handlers/pagehandler.php?handler=search&page=$1
+# rule for rewrite module test during install - can be removed after installation
+RewriteRule ^modrewrite.php$ install.php
+
</IfModule>
diff --git a/install.php b/install.php
index 83d0a40c7..6573e6b2c 100644
--- a/install.php
+++ b/install.php
@@ -4,35 +4,18 @@
*
* @package Elgg
* @subpackage Core
- * @author Curverider Ltd
* @link http://elgg.org/
*/
-/**
- * Start the Elgg engine
- */
-require_once(dirname(__FILE__) . "/engine/start.php");
-global $CONFIG;
-
-elgg_set_viewtype('failsafe');
-/**
- * If we're installed, go back to the homepage
- */
-if ((is_installed() && is_db_installed() && datalist_get('installed'))) {
- forward("index.php");
+// check for PHP 4 before we do anything else
+if (version_compare(PHP_VERSION, '5.0.0', '<')) {
+ echo "Your server's version of PHP (" . PHP_VERSION . ") is too old to run Elgg.\n";
+ exit;
}
-/**
- * Install the database
- */
-if (!is_db_installed()) {
- validate_platform();
- run_sql_script(dirname(__FILE__) . "/engine/schema/mysql.sql");
- init_site_secret();
- system_message(elgg_echo("installation:success"));
-}
+require_once(dirname(__FILE__) . "/install/ElggInstaller.php");
-/**
- * Load the front page
- */
-page_draw(elgg_echo("installation:settings"), elgg_view_layout("one_column", elgg_view("settings/install"))); \ No newline at end of file
+$installer = new ElggInstaller();
+
+$step = get_input('step', 'welcome');
+$installer->run($step);
diff --git a/install/ElggInstaller.php b/install/ElggInstaller.php
new file mode 100644
index 000000000..6d1553572
--- /dev/null
+++ b/install/ElggInstaller.php
@@ -0,0 +1,1274 @@
+<?php
+/**
+ * Elgg Installer.
+ * Controller for installing Elgg.
+ *
+ * @package Elgg
+ * @subpackage Installer
+ * @author Curverider Ltd
+ * @link http://elgg.org/
+ */
+
+class ElggInstaller {
+
+ protected $steps = array(
+ 'welcome',
+ 'requirements',
+ 'database',
+ 'settings',
+ 'admin',
+ 'complete',
+ );
+
+ protected $status = array(
+ 'database' => FALSE,
+ 'settings' => FALSE,
+ 'admin' => FALSE,
+ );
+
+ protected $isAction;
+
+ /**
+ * Constructor bootstraps the Elgg engine
+ */
+ public function __construct() {
+ $this->isAction = $_SERVER['REQUEST_METHOD'] === 'POST';
+
+ $this->bootstrapConfig();
+
+ $this->bootstrapEngine();
+
+ elgg_set_viewtype('failsafe');
+
+ set_error_handler('__elgg_php_error_handler');
+ set_exception_handler('__elgg_php_exception_handler');
+ }
+
+ /**
+ * Dispatches a request to one of the step controllers
+ *
+ * @param string $step
+ */
+ public function run($step) {
+
+ // check if this a mod rewrite test coming in
+ $this->runModRewriteTest();
+
+ if (!in_array($step, $this->getSteps())) {
+ throw new InstallationException("$step is an unknown installation step.");
+ }
+
+ $this->setInstallStatus();
+
+ $this->checkInstallCompletion($step);
+
+ // check if this is an install being resumed
+ $this->resumeInstall($step);
+
+ $this->finishBootstraping($step);
+
+ $params = $this->getPostVariables();
+ $this->$step($params);
+ }
+
+ /**
+ * Renders the data passed by a controller
+ *
+ * @param string $step
+ * @param array $vars
+ */
+ protected function render($step, $vars = array()) {
+
+ $vars['next_step'] = $this->getNextStep($step);
+
+ $title = elgg_echo("install:$step");
+ $body = elgg_view("install/pages/$step", $vars);
+ page_draw(
+ $title,
+ $body,
+ 'page_shells/install',
+ array(
+ 'step' => $step,
+ 'steps' => $this->getSteps(),
+ )
+ );
+ exit;
+ }
+
+ /**
+ * Step controllers
+ */
+
+ /**
+ * Welcome controller
+ *
+ * @param array $vars Not used
+ */
+ protected function welcome($vars) {
+ $this->render('welcome');
+ }
+
+ /**
+ * Requirements controller
+ *
+ * Checks version of php, libraries, permissions, and rewrite rules
+ *
+ * @param array $vars
+ */
+ protected function requirements($vars) {
+
+ $report = array();
+
+ // check PHP parameters and libraries
+ $this->checkPHP($report);
+
+ // @todo - rewrite this to handle different web servers
+ // attempt to create .htaccess file
+ $htaccessExists = $this->createHtaccess($report);
+
+ // check rewrite module
+ if ($htaccessExists) {
+ $this->checkRewriteModule($report);
+ }
+
+ // check for existence of settings file
+ if ($this->checkSettingsFile() != TRUE) {
+ // no file, so check permissions on engine directory
+ $this->checkEngineDir($report);
+ }
+
+ // check the database later
+ $report['database'] = array(array(
+ 'severity' => 'info',
+ 'message' => elgg_echo('install:check:database')
+ ));
+
+ // any failures?
+ $numFailures = $this->countNumConditions($report, 'failure');
+
+ // any warnings
+ $numWarnings = $this->countNumConditions($report, 'warning');
+
+
+ $params = array(
+ 'report' => $report,
+ 'num_failures' => $numFailures,
+ 'num_warnings' => $numWarnings,
+ );
+
+ $this->render('requirements', $params);
+ }
+
+ /**
+ * Database set up controller
+ *
+ * Creates the settings.php file and creates the database tables
+ *
+ * @param array $submissionVars Submitted form variables
+ */
+ protected function database($submissionVars) {
+
+ $formVars = array(
+ 'dbuser' => array(
+ 'type' => 'text',
+ 'value' => '',
+ 'required' => TRUE,
+ ),
+ 'dbpassword' => array(
+ 'type' => 'password',
+ 'value' => '',
+ 'required' => TRUE,
+ ),
+ 'dbname' => array(
+ 'type' => 'text',
+ 'value' => '',
+ 'required' => TRUE,
+ ),
+ 'dbhost' => array(
+ 'type' => 'text',
+ 'value' => 'localhost',
+ 'required' => TRUE,
+ ),
+ 'dbprefix' => array(
+ 'type' => 'text',
+ 'value' => 'elgg_',
+ 'required' => TRUE,
+ ),
+ );
+
+ if ($this->checkSettingsFile()) {
+ // user manually created settings file so we fake out action test
+ $this->isAction = TRUE;
+ }
+
+ if ($this->isAction) {
+ do {
+ // only create settings file if it doesn't exist
+ if (!$this->checkSettingsFile()) {
+ if (!$this->validateDatabaseVars($submissionVars, $formVars)) {
+ // error so we break out of action and serve same page
+ break;
+ }
+
+ if (!$this->createSettingsFile($submissionVars)) {
+ break;
+ }
+ }
+
+ // check db version and connect
+ if (!$this->connectToDatabase()) {
+ break;
+ }
+
+ if (!$this->installDatabase()) {
+ break;
+ }
+
+ system_message('Database has been installed.');
+
+ $this->continueToNextStep('database');
+ } while (FALSE); // PHP doesn't support breaking out of if statements
+ }
+
+ $formVars = $this->makeFormSticky($formVars, $submissionVars);
+
+ $params = array('variables' => $formVars,);
+
+ if ($this->checkSettingsFile()) {
+ // settings file exists and we're here so failed to create database
+ $params['failure'] = TRUE;
+ }
+
+ $this->render('database', $params);
+ }
+
+ /**
+ * Site settings controller
+ *
+ * Sets the site name, URL, data directory, etc.
+ *
+ * @param array $submissionVars
+ */
+ protected function settings($submissionVars) {
+ global $CONFIG;
+
+ $languages = get_installed_translations();
+ $formVars = array(
+ 'sitename' => array(
+ 'type' => 'text',
+ 'value' => 'New Elgg site',
+ 'required' => TRUE,
+ ),
+ 'siteemail' => array(
+ 'type' => 'text',
+ 'value' => '',
+ 'required' => FALSE,
+ ),
+ 'wwwroot' => array(
+ 'type' => 'text',
+ 'value' => $CONFIG->wwwroot,
+ 'required' => TRUE,
+ ),
+ 'path' => array(
+ 'type' => 'text',
+ 'value' => $CONFIG->path,
+ 'required' => TRUE,
+ ),
+ 'dataroot' => array(
+ 'type' => 'text',
+ 'value' => '',
+ 'required' => TRUE,
+ ),
+ 'language' => array(
+ 'type' => 'pulldown',
+ 'value' => 'en',
+ 'options_values' => $languages,
+ 'required' => TRUE,
+ ),
+ 'siteaccess' => array(
+ 'type' => 'access',
+ 'value' => ACCESS_PUBLIC,
+ 'required' => TRUE,
+ ),
+ );
+
+ if ($this->isAction) {
+ do {
+ if (!$this->validateSettingsVars($submissionVars, $formVars)) {
+ break;
+ }
+
+ if (!$this->saveSiteSettings($submissionVars)) {
+ break;
+ }
+
+ system_message('Site settings have been saved.');
+
+ $this->continueToNextStep('settings');
+
+ } while (FALSE); // PHP doesn't support breaking out of if statements
+ }
+
+ $formVars = $this->makeFormSticky($formVars, $submissionVars);
+
+ $this->render('settings', array('variables' => $formVars));
+ }
+
+ /**
+ * Admin account controller
+ *
+ * Creates an admin user account
+ *
+ * @param array $submissionVars
+ */
+ protected function admin($submissionVars) {
+ $formVars = array(
+ 'displayname' => array(
+ 'type' => 'text',
+ 'value' => '',
+ 'required' => TRUE,
+ ),
+ 'email' => array(
+ 'type' => 'text',
+ 'value' => '',
+ 'required' => TRUE,
+ ),
+ 'username' => array(
+ 'type' => 'text',
+ 'value' => '',
+ 'required' => TRUE,
+ ),
+ 'password1' => array(
+ 'type' => 'password',
+ 'value' => '',
+ 'required' => TRUE,
+ ),
+ 'password2' => array(
+ 'type' => 'password',
+ 'value' => '',
+ 'required' => TRUE,
+ ),
+ );
+
+ if ($this->isAction) {
+ do {
+ if (!$this->validateAdminVars($submissionVars, $formVars)) {
+ break;
+ }
+
+ if (!$this->createAdminAccount($submissionVars)) {
+ break;
+ }
+
+ system_message('Admin account has been created.');
+
+ $this->continueToNextStep('admin');
+
+ } while (FALSE); // PHP doesn't support breaking out of if statements
+ }
+
+ $formVars = $this->makeFormSticky($formVars, $submissionVars);
+
+ $this->render('admin', array('variables' => $formVars));
+ }
+
+ /**
+ * Controller for last step
+ *
+ * @param array $vars
+ */
+ protected function complete($vars) {
+
+ $this->render('complete');
+ }
+
+ /**
+ * Step management
+ */
+
+ /**
+ * Get an array of steps
+ *
+ * @return array
+ */
+ protected function getSteps() {
+ return $this->steps;
+ }
+
+ /**
+ * Forwards the browser to the next step
+ *
+ * @param string $currentStep
+ */
+ protected function continueToNextStep($currentStep) {
+ $this->isAction = FALSE;
+ forward($this->getNextStepUrl($currentStep));
+ }
+
+ /**
+ * Get the next step as a string
+ *
+ * @param string $currentStep
+ * @return string
+ */
+ protected function getNextStep($currentStep) {
+ return $this->steps[1 + array_search($currentStep, $this->steps)];
+ }
+
+ /**
+ * Get the URL of the next step
+ *
+ * @param string $currentStep
+ * @return string
+ */
+ protected function getNextStepUrl($currentStep) {
+ global $CONFIG;
+ $nextStep = $this->getNextStep($currentStep);
+ return "{$CONFIG->wwwroot}install.php?step=$nextStep";
+ }
+
+ /**
+ * Check the different nstall steps for completion
+ */
+ protected function setInstallStatus() {
+ global $CONFIG;
+
+ $settingsCreated = $this->checkSettingsFile();
+ if ($settingsCreated == FALSE) {
+ return;
+ }
+
+ $this->loadSettingsFile();
+
+ // must be able to connect to database to jump install steps
+ $dbSettingsPass = $this->checkDatabaseSettings(
+ $CONFIG->dbuser,
+ $CONFIG->dbpass,
+ $CONFIG->dbname,
+ $CONFIG->dbhost
+ );
+ if ($dbSettingsPass == FALSE) {
+ return;
+ }
+
+ if (!include_once("{$CONFIG->path}engine/lib/database.php")) {
+ throw new InstallationException("Could not load database.php");
+ }
+
+ // check that the config table has been created
+ $query = "show tables";
+ $result = get_data($query);
+ if ($result) {
+ foreach ($result as $table) {
+ $table = (array) $table;
+ if (in_array("{$CONFIG->dbprefix}config", $table)) {
+ $this->status['database'] = TRUE;
+ }
+ }
+ if ($this->status['database'] == FALSE) {
+ return;
+ }
+ }
+
+ // check that the config table has entries
+ $query = "SELECT COUNT(*) AS total FROM {$CONFIG->dbprefix}config";
+ $result = get_data($query);
+ if ($result && $result[0]->total > 0) {
+ $this->status['settings'] = TRUE;
+ } else {
+ return;
+ }
+
+ // check that the users entity table has an entry
+ $query = "SELECT COUNT(*) AS total FROM {$CONFIG->dbprefix}users_entity";
+ $result = get_data($query);
+ if ($result && $result[0]->total > 0) {
+ $this->status['admin'] = TRUE;
+ } else {
+ return;
+ }
+ }
+
+ /**
+ * Security check to ensure the installer cannot be run after installation
+ * has finished. If this is detected, the viewer is sent to the front page.
+ *
+ * @param string $step
+ */
+ protected function checkInstallCompletion($step) {
+ if ($step != 'complete') {
+ if (!in_array(FALSE, $this->status)) {
+ // install complete but someone is trying to view an install page
+ forward();
+ }
+ }
+ }
+
+ /**
+ * Check if this is a case of a install being resumed and figure
+ * out where to continue from. Returns the best guess on the step.
+ *
+ * @param string $step
+ * @return string
+ */
+ protected function resumeInstall($step) {
+ global $CONFIG;
+
+ // only do a resume from the first step
+ if ($step !== 'welcome') {
+ return;
+ }
+
+ if ($this->status['database'] == FALSE) {
+ return;
+ }
+
+ if ($this->status['settings'] == FALSE) {
+ forward("{$CONFIG->wwwroot}install.php?step=settings");
+ }
+
+ if ($this->status['admin'] == FALSE) {
+ forward("{$CONFIG->wwwroot}install.php?step=admin");
+ }
+
+ // everything appears to be set up
+ forward("{$CONFIG->wwwroot}install.php?step=complete");
+ }
+
+ /**
+ * Bootstraping
+ */
+
+ /**
+ * Load the essential libraries of the engine
+ */
+ protected function bootstrapEngine() {
+ global $CONFIG;
+
+ $lib_dir = $CONFIG->path . 'engine/lib/';
+
+ // bootstrapping with required files in a required order
+ $required_files = array(
+ 'exceptions.php', 'elgglib.php', 'views.php', 'access.php', 'system_log.php', 'export.php',
+ 'sessions.php', 'languages.php', 'input.php', 'install.php', 'cache.php', 'output.php'
+ );
+
+ foreach ($required_files as $file) {
+ $path = $lib_dir . $file;
+ if (!include($path)) {
+ echo "Could not load file '$path'. "
+ . 'Please check your Elgg installation for all required files.';
+ exit;
+ }
+ }
+ }
+
+ /**
+ * Load remaining engine libraries and complete bootstraping (see start.php)
+ *
+ * @param string $step
+ */
+ protected function finishBootstraping($step) {
+
+ // install has its own session handling
+ session_name('Elgg');
+ session_start();
+ unregister_elgg_event_handler('boot', 'system', 'session_init');
+
+ // once the database has been created, load rest of engine
+ $dbIndex = array_search('database', $this->getSteps());
+ $stepIndex = array_search($step, $this->getSteps());
+
+ if ($stepIndex > $dbIndex) {
+ global $CONFIG;
+ $lib_dir = $CONFIG->path . 'engine/lib/';
+
+ $this->loadSettingsFile();
+
+ $lib_files = array(
+ // these want to be loaded first apparently?
+ 'database.php', 'actions.php',
+
+ 'admin.php', 'annotations.php', 'api.php',
+ 'calendar.php', 'configuration.php', 'cron.php', 'entities.php',
+ 'extender.php', 'filestore.php', 'group.php',
+ 'location.php', 'mb_wrapper.php',
+ 'memcache.php', 'metadata.php', 'metastrings.php', 'notification.php',
+ 'objects.php', 'opendd.php', 'pagehandler.php',
+ 'pageowner.php', 'pam.php', 'plugins.php', 'query.php',
+ 'relationships.php', 'river.php', 'sites.php', 'social.php',
+ 'statistics.php', 'tags.php', 'usersettings.php',
+ 'users.php', 'version.php', 'widgets.php', 'xml.php', 'xml-rpc.php'
+ );
+
+ foreach ($lib_files as $file) {
+ $path = $lib_dir . $file;
+ if (!include_once($path)) {
+ throw new InstallationException("Could not load {$file}");
+ }
+ }
+
+ set_default_config();
+
+ trigger_elgg_event('boot', 'system');
+ trigger_elgg_event('init', 'system');
+ }
+ }
+
+ /**
+ * Set up configuration variables
+ */
+ protected function bootstrapConfig() {
+ global $CONFIG;
+ if (!isset($CONFIG)) {
+ $CONFIG = new stdClass;
+ }
+
+ $CONFIG->wwwroot = $this->getBaseUrl();
+ $CONFIG->url = $CONFIG->wwwroot;
+ $CONFIG->path = dirname(dirname(__FILE__)) . '/';
+ }
+
+ /**
+ * Get the best guess at the base URL
+ * @todo Should this be a core function?
+ * @return string
+ */
+ protected function getBaseUrl() {
+ $protocol = 'http';
+ if (!empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") {
+ $protocol = 'https';
+ }
+ $port = ':' . $_SERVER["SERVER_PORT"];
+ if ($port == ':80' || $port == ':443') {
+ $port = '';
+ }
+ $uri = $_SERVER['REQUEST_URI'];
+ $cutoff = strpos($uri, 'install.php');
+ $uri = substr($uri, 0, $cutoff);
+
+ $url = "$protocol://{$_SERVER['SERVER_NAME']}$port{$uri}";
+ return $url;
+ }
+
+ function loadSettingsFile() {
+ global $CONFIG;
+
+ if (!include_once("{$CONFIG->path}engine/settings.php")) {
+ throw new InstallationException("Elgg could not load the settings file. It does not exist or there is a permissions issue.");
+ }
+ }
+
+ /**
+ * Action handling methods
+ */
+
+ /**
+ * Return an associative array of post variables
+ * (could be selective based on expected variables)
+ *
+ * @return array
+ */
+ protected function getPostVariables() {
+ $vars = array();
+ foreach ($_POST as $k => $v) {
+ $vars[$k] = $v;
+ }
+ return $vars;
+ }
+
+ /**
+ * If form is reshown, remember previously submitted variables
+ *
+ * @param array $formVars
+ * @param array $submissionVars
+ * @return array
+ */
+ protected function makeFormSticky($formVars, $submissionVars) {
+ foreach ($submissionVars as $field => $value) {
+ $formVars[$field]['value'] = $value;
+ }
+ return $formVars;
+ }
+
+ /**
+ * Requirement checks support methods
+ */
+
+ /**
+ * Create Elgg's .htaccess file or confirm that it exists
+ *
+ * @param array $report Reference to the report array
+ * @return bool
+ */
+ protected function createHtaccess(&$report) {
+ global $CONFIG;
+
+ $filename = "{$CONFIG->path}.htaccess";
+ if (file_exists($filename)) {
+ // check that this is the Elgg .htaccess
+ $data = file_get_contents($filename);
+ if ($data === FALSE) {
+ // don't have permission to read the file
+ }
+ if (strpos($data, 'Elgg') === FALSE) {
+ $report['htaccess'] = array(
+ array(
+ 'severity' => 'failure',
+ 'message' => elgg_echo('install:check:htaccess_exists'),
+ )
+ );
+ return FALSE;
+ } else {
+ // Elgg .htaccess is already there
+ return TRUE;
+ }
+ }
+
+ if (!is_writable($CONFIG->path)) {
+ $report['htaccess'] = array(
+ array(
+ 'severity' => 'failure',
+ 'message' => elgg_echo('install:check:root'),
+ )
+ );
+ return FALSE;
+ }
+
+ // create the .htaccess file
+ $result = copy("{$CONFIG->path}htaccess_dist", $filename);
+ if (!$result) {
+ $report['htaccess'] = array(
+ array(
+ 'severity' => 'failure',
+ 'message' => elgg_echo('install:check:htaccess_fail'),
+ )
+ );
+ }
+
+ return $result;
+ }
+
+ /**
+ * Check that the engine dir is writable
+ * @param array $report
+ * @return bool
+ */
+ protected function checkEngineDir(&$report) {
+ global $CONFIG;
+
+ $writable = is_writable("{$CONFIG->path}engine");
+ if (!$writable) {
+ $report['engine'] = array(
+ array(
+ 'severity' => 'failure',
+ 'message' => elgg_echo('install:check:enginedir'),
+ )
+ );
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * Check that the settings file exists
+ * @return bool
+ */
+ protected function checkSettingsFile() {
+ global $CONFIG;
+
+ if (is_readable("{$CONFIG->path}engine/settings.php")) {
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ /**
+ * Check version of PHP, extensions, and variables
+ * @param array $report
+ */
+ protected function checkPHP(&$report) {
+ $phpReport = array();
+
+ $elgg_php_version = '5.2.0';
+ if (version_compare(PHP_VERSION, $elgg_php_version, '<')) {
+ $phpReport[] = array(
+ 'severity' => 'failure',
+ 'message' => sprintf(elgg_echo('install:check:php:version'), $elgg_php_version, PHP_VERSION)
+ );
+ }
+
+ $this->checkPhpExtensions($phpReport);
+
+ $this->checkPhpDirectives($phpReport);
+
+ if (count($phpReport) == 0) {
+ $phpReport[] = array(
+ 'severity' => 'pass',
+ 'message' => elgg_echo('install:check:php:success')
+ );
+ }
+
+ $report['php'] = $phpReport;
+ }
+
+ /**
+ * Check the server's PHP extensions
+ *
+ * @param array $phpReport
+ */
+ protected function checkPhpExtensions(&$phpReport) {
+ $extensions = get_loaded_extensions();
+ $requiredExtensions = array(
+ 'mysql',
+ 'json',
+ 'xml',
+ 'gd',
+ );
+ foreach ($requiredExtensions as $extension) {
+ if (!in_array($extension, $extensions)) {
+ $phpReport[] = array(
+ 'severity' => 'failure',
+ 'message' => sprintf(elgg_echo('install:check:php:extension'), $extension)
+ );
+ }
+ }
+
+ $recommendedExtensions = array(
+ 'mbstring',
+ );
+ foreach ($recommendedExtensions as $extension) {
+ if (!in_array($extension, $extensions)) {
+ $phpReport[] = array(
+ 'severity' => 'warning',
+ 'message' => sprintf(elgg_echo('install:check:php:extension:recommend'), $extension)
+ );
+ }
+ }
+ }
+
+ /**
+ * Check PHP parameters
+ *
+ * @param array $phpReport
+ */
+ protected function checkPhpDirectives(&$phpReport) {
+ if (ini_get('open_basedir')) {
+ $phpReport[] = array(
+ 'severity' => 'warning',
+ 'message' => elgg_echo("install:check:php:open_basedir")
+ );
+ }
+
+ if (ini_get('safe_mode')) {
+ $phpReport[] = array(
+ 'severity' => 'warning',
+ 'message' => elgg_echo("install:check:php:safe_mode")
+ );
+ }
+ }
+
+ /**
+ * Confirm that Apache's rewrite module and AllowOverride are set up
+ * @param array $report
+ * @return bool
+ */
+ protected function checkRewriteModule(&$report) {
+ global $CONFIG;
+
+ $url = "{$CONFIG->wwwroot}modrewrite.php";
+
+ if (function_exists('curl_init')) {
+ // try curl if installed
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ $response = curl_exec($ch);
+ curl_close($ch);
+ $result = $response === 'success';
+ } else if (ini_get('allow_url_fopen')) {
+ // use file_get_contents as fallback
+ $data = file_get_contents($url);
+ $result = $data === 'success';
+ } else {
+ $report['htaccess'] = array(
+ array(
+ 'severity' => 'warning',
+ 'message' => elgg_echo('install:check:rewrite:unknown'),
+ )
+ );
+ return FALSE;
+ }
+
+ if ($result) {
+ $report['htaccess'] = array(
+ array(
+ 'severity' => 'pass',
+ 'message' => elgg_echo('install:check:rewrite:success'),
+ )
+ );
+ } else {
+ $report['htaccess'] = array(
+ array(
+ 'severity' => 'failure',
+ 'message' => elgg_echo('install:check:rewrite:fail'),
+ )
+ );
+ }
+
+ return $result;
+ }
+
+ /**
+ * Check if the request is coming from the mod rewrite test on the
+ * requirements page.
+ */
+ protected function runModRewriteTest() {
+ if (strpos($_SERVER['REQUEST_URI'], 'modrewrite.php') !== FALSE) {
+ echo 'success';
+ exit;
+ }
+ }
+
+ /**
+ * Count the number of failures in the requirements report
+ *
+ * @param array $report
+ * @param string $condition 'failure' or 'warning'
+ * @return int
+ */
+ protected function countNumConditions($report, $condition) {
+ $count = 0;
+ foreach ($report as $category => $checks) {
+ foreach ($checks as $check) {
+ if ($check['severity'] === $condition) {
+ $count++;
+ }
+ }
+ }
+
+ return $count;
+ }
+
+
+ /**
+ * Database support methods
+ */
+
+ /**
+ * Validate the variables for the database step
+ *
+ * @param array $submissionVars
+ * @param array $formVars
+ * @return bool
+ */
+ protected function validateDatabaseVars($submissionVars, $formVars) {
+
+ foreach ($formVars as $field => $info) {
+ if ($info['required'] == TRUE && !$submissionVars[$field]) {
+ $name = elgg_echo("installation:database:label:$field");
+ register_error("$name is required");
+ return FALSE;
+ }
+ }
+
+ return $this->checkDatabaseSettings(
+ $submissionVars['dbuser'],
+ $submissionVars['dbpassword'],
+ $submissionVars['dbname'],
+ $submissionVars['dbhost']
+ );
+ }
+
+ /**
+ * Confirm the settings for the database
+ *
+ * @param string $user
+ * @param string $password
+ * @param string $dbname
+ * @param string $host
+ * @return bool
+ */
+ function checkDatabaseSettings($user, $password, $dbname, $host) {
+ $mysql_dblink = mysql_connect($host, $user, $password, true);
+ if ($mysql_dblink == FALSE) {
+ register_error('Unable to connect to the database with these settings.');
+ return $FALSE;
+ }
+
+ $result = mysql_select_db($dbname, $mysql_dblink);
+
+ // check MySQL version - must be 5.0 or >
+ $version = mysql_get_server_info();
+ $points = explode('.', $version);
+ if ($points[0] < 5) {
+ register_error("MySQL must be 5.0 or above. Your server is using $version.");
+ return FALSE;
+ }
+
+ mysql_close($mysql_dblink);
+
+ if (!$result) {
+ register_error("Unable to use database $dbname");
+ }
+
+ return $result;
+ }
+
+ /**
+ * Writes the settings file to the engine directory
+ *
+ * @param array $params
+ * @return bool
+ */
+ protected function createSettingsFile($params) {
+ global $CONFIG;
+
+ $templateFile = "{$CONFIG->path}engine/settings.example.php";
+ $template = file_get_contents($templateFile);
+ if (!$template) {
+ register_error('Unable to read engine/settings.example.php');
+ return FALSE;
+ }
+
+ foreach ($params as $k => $v) {
+ $template = str_replace("{{".$k."}}", $v, $template);
+ }
+
+ $settingsFilename = "{$CONFIG->path}engine/settings.php";
+ $result = file_put_contents($settingsFilename, $template);
+ if (!$result) {
+ register_error('Unable to write engine/settings.php');
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * Bootstrap database connection before entire engine is available
+ *
+ * @return bool
+ */
+ protected function connectToDatabase() {
+ global $CONFIG;
+
+ if (!include_once("{$CONFIG->path}engine/settings.php")) {
+ register_error("Elgg could not load the settings file.");
+ return FALSE;
+ }
+
+ if (!include_once("{$CONFIG->path}engine/lib/database.php")) {
+ register_error("Elgg could not load the database library.");
+ return FALSE;
+ }
+
+ try {
+ setup_db_connections();
+ } catch (Exception $e) {
+ register_error($e->getMessage());
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * Create the database tables
+ *
+ * @return bool
+ */
+ protected function installDatabase() {
+ global $CONFIG;
+
+ try {
+ run_sql_script("{$CONFIG->path}engine/schema/mysql.sql");
+ } catch (Exception $e) {
+ register_error($e->getMessage());
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * Site settings support methods
+ */
+
+ /**
+ * Validate the site settings form variables
+ *
+ * @param array $submissionVars
+ * @param array $formVars
+ * @return bool
+ */
+ protected function validateSettingsVars($submissionVars, $formVars) {
+
+ foreach ($formVars as $field => $info) {
+ if ($info['required'] == TRUE && !$submissionVars[$field]) {
+ $name = elgg_echo("installation:settings:label:$field");
+ register_error("$name is required");
+ return FALSE;
+ }
+ }
+
+ // check that data root is writable
+ if (!is_writable($submissionVars['dataroot'])) {
+ register_error("Your data directory {$submissionVars['dataroot']} is not writable by the web server.");
+ return FALSE;
+ }
+
+ // check that data root is not subdirectory of Elgg root
+ if (stripos($submissionVars['dataroot'], $submissionVars['path']) !== FALSE) {
+ register_error("Your data directory {$submissionVars['dataroot']} must be outside of your install path for security.");
+ return FALSE;
+ }
+
+ // @todo move is_email_address to a better library than users.php
+ // check that email address is email address
+ //if ($submissionVars['siteemail'] && !is_email_address($submissionVars['siteemail'])) {
+ // register_error("{$submissionVars['']} is not a valid email address.");
+ // return FALSE;
+ //}
+
+ // @todo check that url is a url
+
+
+ return TRUE;
+ }
+
+ /**
+ * Initialize the site including site entity, plugins, and configuration
+ *
+ * @param array $submissionVars
+ * @return bool
+ */
+ protected function saveSiteSettings($submissionVars) {
+ global $CONFIG;
+
+ // ensure that file path, data path, and www root end in /
+ $submissionVars['path'] = sanitise_filepath($submissionVars['path']);
+ $submissionVars['dataroot'] = sanitise_filepath($submissionVars['dataroot']);
+ $submissionVars['wwwroot'] = sanitise_filepath($submissionVars['wwwroot']);
+
+ $site = new ElggSite();
+ $site->name = $submissionVars['sitename'];
+ $site->url = $submissionVars['wwwroot'];
+ $site->access_id = ACCESS_PUBLIC;
+ $site->email = $submissionVars['siteemail'];
+ $guid = $site->save();
+
+ if (!$guid) {
+ register_error("Unable to create the site.");
+ return FALSE;
+ }
+
+ // bootstrap site info
+ $CONFIG->site_guid = $guid;
+ $CONFIG->site = $site;
+
+ datalist_set('installed', time());
+ datalist_set('path', $submissionVars['path']);
+ datalist_set('dataroot', $submissionVars['dataroot']);
+ datalist_set('default_site', $site->getGUID());
+ datalist_set('version', get_version());
+
+ set_config('view', 'default', $site->getGUID());
+ set_config('language', $submissionVars['language'], $site->getGUID());
+ set_config('default_access', $submissionVars['siteaccess'], $site->getGUID());
+ set_config('allow_registration', TRUE, $site->getGUID());
+ set_config('walled_garden', FALSE, $site->getGUID());
+
+ $this->enablePlugins();
+
+ // reset the views path in case of installing over an old data dir.
+ $dataroot = datalist_get('dataroot');
+ $cache = new ElggFileCache($dataroot);
+ $cache->delete('view_paths');
+
+ return TRUE;
+ }
+
+ /**
+ * Enable a set of default plugins
+ */
+ protected function enablePlugins() {
+ // activate plugins with manifest.xml: elgg_install_state = enabled
+ $plugins = get_plugin_list();
+ foreach ($plugins as $plugin) {
+ if ($manifest = load_plugin_manifest($plugin)) {
+ if (isset($manifest['elgg_install_state']) && $manifest['elgg_install_state'] == 'enabled') {
+ enable_plugin($plugin);
+ }
+ }
+ }
+ }
+
+ /**
+ * Admin account support methods
+ */
+
+ /**
+ * Validate account form variables
+ *
+ * @param array $submissionVars
+ * @param array $formVars
+ * @return bool
+ */
+ protected function validateAdminVars($submissionVars, $formVars) {
+
+ foreach ($formVars as $field => $info) {
+ if ($info['required'] == TRUE && !$submissionVars[$field]) {
+ $name = elgg_echo("installation:admin:label:$field");
+ register_error("$name is required");
+ return FALSE;
+ }
+ }
+
+ if ($submissionVars['password1'] !== $submissionVars['password2']) {
+ register_error("Your passwords must match.");
+ return FALSE;
+ }
+
+ if (trim($submissionVars['password1']) == "") {
+ register_error("Password cannot be empty.");
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /**
+ * Create a user account for the admin
+ *
+ * @param array $submissionVars
+ * @return bool
+ */
+ protected function createAdminAccount($submissionVars) {
+ global $CONFIG;
+
+ $guid = register_user(
+ $submissionVars['username'],
+ $submissionVars['password1'],
+ $submissionVars['displayname'],
+ $submissionVars['email']
+ );
+
+ if (!$guid) {
+ register_error("Unable to create an admin account.");
+ return FALSE;
+ }
+
+ // @todo - register plugin hook instead for can edit
+ // need a logged in user to set admin flag so we go directly to database
+ $result = update_data("UPDATE {$CONFIG->dbprefix}users_entity set admin='yes' where guid=$guid");
+ if (!$result) {
+ register_error("Unable to give new user account admin privileges.");
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+}
diff --git a/install/install.css b/install/install.css
new file mode 100644
index 000000000..de10f10a5
--- /dev/null
+++ b/install/install.css
@@ -0,0 +1,266 @@
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, font, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ outline: 0;
+ font-weight: inherit;
+ font-style: inherit;
+ font-size: 100%;
+ font-family: inherit;
+ vertical-align: baseline;
+}
+
+body {
+ color: #333333;
+ background: #4690d6;
+ font-size: 80%;
+ font-family: "Lucida Grande",Arial,Tahoma,Verdana,sans-serif;
+ text-align: left;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-weight: bold;
+}
+h1 { font-size: 1.8em; }
+h2 { font-size: 1.5em; }
+h3 { font-size: 1.2em; }
+h4 { font-size: 1.0em; }
+h5 { font-size: 0.9em; }
+h6 { font-size: 0.8em; }
+
+a {
+ color: #4690d6;
+ text-decoration: none;
+}
+
+a:hover {
+ color: #0054a7;
+ text-decoration: underline;
+}
+
+p {
+ margin: 0px 0px 15px 0;
+}
+
+img {
+ border: none;
+}
+
+h2 {
+ border-bottom: 1px solid #555555;
+ margin-bottom: 20px;
+}
+
+ul {
+ list-style: none;
+}
+
+.clearfloat {
+ clear:both;
+ height:0;
+ font-size: 1px;
+ line-height: 0px;
+}
+
+#elgg_wrapper {
+ background: white;
+ width: 800px;
+ margin: auto;
+ padding: 10px 40px;
+ margin-top: 20px;
+ border-right: 1px solid #666666;
+ border-bottom: 1px solid #666666;
+}
+#elgg_header {
+ margin: 20px 10px;
+}
+#elgg_sidebar {
+ float: left;
+ width: 250px;
+}
+#elgg_content {
+ float: left;
+ width: 550px;
+ min-height: 320px;
+ padding-bottom: 60px;
+ position: relative;
+}
+#elgg_footer {
+ width: 800px;
+ height: 20px;
+ clear: both;
+ padding: 10px 20px 0 20px;
+ margin: auto;
+ margin-bottom: 40px;
+}
+
+.install_nav {
+ width: 100%;
+ text-align: right;
+ position: absolute;
+ bottom: 0px;
+}
+
+#elgg_footer a {
+ color: white;
+}
+
+#elgg_footer li {
+ float: left;
+ list-style: none;
+ margin-right: 20px;
+}
+
+#elgg_sidebar ol {
+ padding-left: 30px;
+}
+
+#elgg_sidebar li {
+ font-size: 1.2em;
+ margin-bottom: 5px;
+}
+
+.past {
+ text-decoration: line-through;
+}
+.present {
+ font-weight: bold;
+}
+
+.future {
+ color: #cccccc;
+}
+
+h3 {
+ margin: 15px 0 5px;
+}
+
+label {
+ font-weight: bold;
+ color:#333333;
+ font-size: 140%;
+}
+input[type="text"],
+input[type="password"] {
+ font: 120% Arial, Helvetica, sans-serif;
+ padding: 5px;
+ border: 1px solid #cccccc;
+ color:#666666;
+ width:566px;
+}
+.database_settings input[type="text"],
+.database_settings input[type="password"] {
+ width:220px;
+}
+textarea {
+ width: 100%;
+ height: 100%;
+ font: 120% Arial, Helvetica, sans-serif;
+ border: solid 1px #cccccc;
+ padding: 5px;
+ color:#666666;
+}
+textarea:focus, input[type="password"]:focus, input[type="text"]:focus {
+ border: solid 1px #4690d6;
+ background: #e4ecf5;
+ color:#333333;
+}
+input[type="submit"] {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 16px;
+ font-weight: bold;
+ color: #ffffff;
+ background: #4690d6;
+ border: 4px solid #4690d6;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ width: auto;
+ height: 35px;
+ padding: 2px 6px 2px 6px;
+ margin: 10px 0 10px 0;
+ cursor: pointer;
+ float: right;
+}
+
+input[type="submit"]:hover {
+ background: #0054a7;
+ border: 4px solid #0054a7;
+}
+
+select {
+ display: block;
+ padding: 5px;
+}
+
+.install_nav a {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 16px;
+ font-weight: bold;
+ color: #ffffff;
+ background: #4690d6;
+ border: 4px solid #4690d6;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ padding: 2px 9px 2px 9px;
+ margin: 10px;
+ cursor: pointer;
+ float: right;
+}
+
+.install_nav a:hover {
+ text-decoration: none;
+ background: #0054a7;
+ border: 4px solid #0054a7;
+}
+.install_nav .disabled, .install_nav .disabled:hover {
+ background: #555555;
+ border-color: #555555;
+ cursor: default;
+}
+
+#elgg_system_message {
+ padding: 3px 10px 3px 10px;
+ margin-bottom: 20px;
+}
+
+.success {
+ border: 1px solid #00cc00;
+ background: #ccffcc;
+}
+
+.error {
+ border: 1px solid #D3322A;
+ background: #F7DAD8;
+}
+
+#elgg_content li {
+ margin-top: 5px;
+ padding: 5px;
+}
+
+.pass {
+ border: 1px solid #00cc00;
+ background: #ccffcc;
+}
+
+.warning {
+ border: 1px solid #ded0a9;
+ background: #FEF5AA;
+}
+
+.failure {
+ border: 1px solid #D3322A;
+ background: #F7DAD8;
+}
+
+.info {
+ border: 1px solid #aaaaaa;
+ background: #ffffff;
+}
diff --git a/languages/en.php b/languages/en.php
index 95ec4ba38..d92aff61e 100644
--- a/languages/en.php
+++ b/languages/en.php
@@ -935,6 +935,107 @@ You cannot reply to this email.",
'actiongatekeeper:pluginprevents' => 'A extension has prevented this form from being submitted.',
/**
+ * Installation
+ * @todo - move to separate language file for install
+ */
+ 'install:welcome' => 'Welcome',
+ 'install:requirements' => 'Requirements check',
+ 'install:database' => 'Database installation',
+ 'install:settings' => 'Configure site',
+ 'install:admin' => 'Create admin account',
+ 'install:complete' => 'Finished',
+
+ 'install:welcome:instructions' => "Installing Elgg has 6 simple steps and reading this welcome is the first one!
+
+If you haven't already, read through the installation instructions included with Elgg (or click the instructions link at the bottom of the page).
+
+If you are ready to proceed, click the Next button.",
+ 'install:requirements:instructions:success' => "Your server passed the requirement checks.",
+ 'install:requirements:instructions:failure' => "Your server failed the requirements check. After you have fixed the below issues, refresh this page.",
+ 'install:requirements:instructions:warning' => "Your server passed the requirements check, but there is at least one warning. We recommend that you check the install troubleshooting page for more details.",
+
+ 'install:require:php' => 'PHP',
+ 'install:require:htaccess' => 'Web server',
+ 'install:require:engine' => 'Settings file',
+ 'install:require:database' => 'Database',
+
+ 'install:check:root' => 'Your web server does not have permission to create an .htaccess file in the root directory of Elgg. You have two choices:
+
+ 1. Change the permissions on the root directory
+
+ 2. Copy the file htaccess_dist to .htaccess',
+
+ 'install:check:php:version' => 'Elgg requires PHP %s or above. This server is using version %s.',
+ 'install:check:php:extension' => 'Elgg requires the PHP extension %s.',
+ 'install:check:php:extension:recommend' => 'It is recommended that the PHP extension %s is installed.',
+ 'install:check:php:open_basedir' => 'The open_basedir PHP directive may prevent Elgg from saving files to its data directory.',
+ 'install:check:php:safe_mode' => 'Running PHP in safe mode is not recommened and may cause problems with Elgg.',
+
+ 'install:check:htaccess_exists' => 'There is an .htaccess file in the root directory of Elgg. Please remove it.',
+ 'install:check:htaccess_fail' => 'Unable to create an .htaccess file in the root directory of Elgg. You will need to copy htaccess_dist to .htaccess',
+ 'install:check:rewrite:success' => 'The test of the rewrite rules was successful.',
+
+ 'install:check:enginedir' => 'Your web server does not have permission to create the settings.php file in the engine directory. You have two choices:
+
+ 1. Change the permissions on the engine directory
+
+ 2. Copy the file settings.example.php to settings.php and follow the instructions in it for setting your database parameters.',
+
+ 'install:check:php:success' => "Your server's PHP satisfies all of Elgg's requirements.",
+ 'install:check:database' => 'The database requirements are checked when Elgg loads its database.',
+
+ 'install:database:instructions' => "If you haven't already created a database for Elgg, do that now. Then fill in the values below to initialize the Elgg database.",
+
+ 'installation:database:label:dbuser' => 'Database Username',
+ 'installation:database:label:dbpassword' => 'Database Password',
+ 'installation:database:label:dbname' => 'Database Name',
+ 'installation:database:label:dbhost' => 'Database Host',
+ 'installation:database:label:dbprefix' => 'Database Table Prefix',
+
+ 'installation:database:help:dbuser' => 'User that has full priviledges to the MySQL database that you created for Elgg',
+ 'installation:database:help:dbpassword' => 'Password for the above database user account',
+ 'installation:database:help:dbname' => 'Name of the Elgg database',
+ 'installation:database:help:dbhost' => 'Hostname of the MySQL server (usually localhost)',
+ 'installation:database:help:dbprefix' => "The prefix given to all of Elgg's tables (usually elgg_)",
+
+ 'install:dbuser' => '',
+
+ 'install:settings:instructions' => "We need some information about the site as we configure Elgg. If you haven't created a data directory for Elgg, please do so before completing this step.",
+
+ 'installation:settings:label:sitename' => 'Site Name',
+ 'installation:settings:label:siteemail' => 'Site Email Address',
+ 'installation:settings:label:wwwroot' => 'Site URL',
+ 'installation:settings:label:path' => 'Elgg Install Directory',
+ 'installation:settings:label:dataroot' => 'Data Directory',
+ 'installation:settings:label:language' => 'Site Language',
+ 'installation:settings:label:siteaccess' => 'Default Site Access',
+
+ 'installation:settings:help:sitename' => 'The name of your new Elgg site',
+ 'installation:settings:help:siteemail' => 'Email address used by Elgg for communication with users',
+ 'installation:settings:help:wwwroot' => 'The address of the site (Elgg usually guesses this correctly)',
+ 'installation:settings:help:path' => 'The directory where you put the Elgg code (Elgg usually guesses this correctly)',
+ 'installation:settings:help:dataroot' => 'The directory that you created for Elgg to save files (the permissions on this directory are checked when you click Next)',
+ 'installation:settings:help:language' => 'The default language for the site',
+ 'installation:settings:help:siteaccess' => 'The default access level for new user created content',
+
+ 'install:admin:instructions' => "It is now time to create an administrator's account.",
+
+ 'installation:admin:label:displayname' => 'Display Name',
+ 'installation:admin:label:email' => 'Email Address',
+ 'installation:admin:label:username' => 'Username',
+ 'installation:admin:label:password1' => 'Password',
+ 'installation:admin:label:password2' => 'Password Again',
+
+ 'installation:admin:help:displayname' => 'The name that is displayed on the site for this account',
+ 'installation:admin:help:email' => '',
+ 'installation:admin:help:username' => 'Account username used for logging in',
+ 'installation:admin:help:password1' => 'Account password must be at least x characters long',
+ 'installation:admin:help:password2' => 'Retype password to confirm',
+
+ 'install:complete:instructions' => 'Your Elgg site is now ready to be used. Click the button below to be taken to your site.',
+
+
+/**
* Word blacklists
*/
'word:blacklist' => 'and, the, then, but, she, his, her, him, one, not, also, about, now, hence, however, still, likewise, otherwise, therefore, conversely, rather, consequently, furthermore, nevertheless, instead, meanwhile, accordingly, this, seems, what, whom, whose, whoever, whomever',
diff --git a/views/failsafe/input/password.php b/views/failsafe/input/password.php
new file mode 100644
index 000000000..461f77955
--- /dev/null
+++ b/views/failsafe/input/password.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Elgg password input
+ * Displays a password input field
+ *
+ * @package Elgg
+ * @subpackage Core
+ * @author Curverider Ltd
+ * @link http://elgg.org/
+ *
+ * @uses $vars['value'] The current value, if any
+ * @uses $vars['js'] Any Javascript to enter into the input tag
+ * @uses $vars['internalname'] The name of the input field
+ *
+ */
+
+$class = $vars['class'];
+if (!$class) {
+ $class = "input_password";
+}
+?>
+
+<input type="password" <?php if ($vars['disabled']) echo ' disabled="yes" '; ?> <?php echo $vars['js']; ?> name="<?php echo $vars['internalname']; ?>" <?php if (isset($vars['internalid'])) echo "id=\"{$vars['internalid']}\""; ?> value="<?php echo htmlentities($vars['value'], ENT_QUOTES, 'UTF-8'); ?>" class="<?php echo $class; ?>" />
diff --git a/views/failsafe/install/footer.php b/views/failsafe/install/footer.php
new file mode 100644
index 000000000..69cd27f66
--- /dev/null
+++ b/views/failsafe/install/footer.php
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Install footer - offers help links
+ */
+?>
+<ul>
+ <li><a href="http://docs.elgg.org/wiki/Installation">Install instructions</a></li>
+ <li><a href="http://docs.elgg.org/wiki/Install_Troubleshooting">Install troubleshooting</a></li>
+ <li><a href="http://community.elgg.org/pg/groups/world/">Elgg community forums</a></li>
+</ul> \ No newline at end of file
diff --git a/views/failsafe/install/forms/admin.php b/views/failsafe/install/forms/admin.php
new file mode 100644
index 000000000..ae83cadea
--- /dev/null
+++ b/views/failsafe/install/forms/admin.php
@@ -0,0 +1,21 @@
+<?php
+/**
+ * Admin account form
+ *
+ * @uses $vars['variables'] Array of form variables. See ElggInstaller.
+ */
+
+$vars['type'] = 'admin';
+$form_body = elgg_view('install/forms/template', $vars);
+
+
+// @todo bug in current_page_url() with :8080 sites
+//$url = current_page_url();
+$url = '/install.php?step=admin';
+
+$params = array(
+ 'body' => $form_body,
+ 'action' => $url,
+ 'disable_security' => TRUE,
+);
+echo elgg_view('input/form', $params);
diff --git a/views/failsafe/install/forms/database.php b/views/failsafe/install/forms/database.php
new file mode 100644
index 000000000..a3fa8dd65
--- /dev/null
+++ b/views/failsafe/install/forms/database.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * Database form
+ *
+ * @uses $vars['variables'] Array of form variables. See ElggInstaller.
+ */
+
+$vars['type'] = 'database';
+$form_body = elgg_view('install/forms/template', $vars);
+
+// @todo bug in current_page_url() with :8080 sites
+//$url = current_page_url();
+$url = '/install.php?step=database';
+
+$params = array(
+ 'body' => $form_body,
+ 'action' => $url,
+ 'disable_security' => TRUE,
+);
+echo elgg_view('input/form', $params);
diff --git a/views/failsafe/install/forms/settings.php b/views/failsafe/install/forms/settings.php
new file mode 100644
index 000000000..67cba10f6
--- /dev/null
+++ b/views/failsafe/install/forms/settings.php
@@ -0,0 +1,20 @@
+<?php
+/**
+ * Site settings form
+ *
+ * @uses $vars['variables'] Array of form variables. See ElggInstaller.
+ */
+
+$vars['type'] = 'settings';
+$form_body = elgg_view('install/forms/template', $vars);
+
+// @todo bug in current_page_url() with :8080 sites
+//$url = current_page_url();
+$url = '/install.php?step=settings';
+
+$params = array(
+ 'body' => $form_body,
+ 'action' => $url,
+ 'disable_security' => TRUE,
+);
+echo elgg_view('input/form', $params);
diff --git a/views/failsafe/install/forms/template.php b/views/failsafe/install/forms/template.php
new file mode 100644
index 000000000..a2d93f42e
--- /dev/null
+++ b/views/failsafe/install/forms/template.php
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Generic form template for install forms
+ *
+ * @uses $vars['variables']
+ * @uses $vars['type'] Type of form: admin, database, settings
+ */
+
+$variables = $vars['variables'];
+$type = $vars['type'];
+
+$form_body = '';
+foreach ($variables as $field => $params) {
+ $label = elgg_echo("installation:$type:label:$field");
+ $help = elgg_echo("installation:$type:help:$field");
+ $params['internalname'] = $field;
+
+ $form_body .= '<p>';
+ $form_body .= "<label>$label</label>";
+ $form_body .= elgg_view("input/{$params['type']}", $params);
+ $form_body .= "<span class=\"install_help\">$help</span>";
+ $form_body .= '</p>';
+}
+
+$form_body .= elgg_view('input/submit', array('value' => elgg_echo('next')));
+
+echo $form_body;
diff --git a/views/failsafe/install/header.php b/views/failsafe/install/header.php
new file mode 100644
index 000000000..d821e31e5
--- /dev/null
+++ b/views/failsafe/install/header.php
@@ -0,0 +1,6 @@
+<?php
+/**
+ * Install header
+ */
+?>
+<h1>Elgg</h1>
diff --git a/views/failsafe/install/nav.php b/views/failsafe/install/nav.php
new file mode 100644
index 000000000..d6a20ea2b
--- /dev/null
+++ b/views/failsafe/install/nav.php
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Navigation for installation pages
+ *
+ * @uses $vars['url'] base url of site
+ * @uses $vars['next_step'] next step as string
+ * @uses $vars['refresh'] should refresh button be shown?
+ * @uses $vars['advance'] should the next button be active?
+ */
+
+
+// has a refresh button been requested
+$refresh = '';
+if (isset($vars['refresh']) && $vars['refresh']) {
+ $refresh_text = elgg_echo('Refresh');
+ $refresh = "<a href=\"\">$refresh_text</a>";
+}
+
+// create next button and selectively disable
+$next_text = elgg_echo('next');
+$next_link = "{$vars['url']}install.php?step={$vars['next_step']}";
+$next = "<a href=\"$next_link\" disable=\"disable\">$next_text</a>";
+if (isset($vars['advance']) && !$vars['advance']) {
+ // disable the next button
+ $next = "<a class=\"disabled\">$next_text</a>";
+}
+
+
+echo <<<___END
+<div class="install_nav">
+ $next
+ $refresh
+</div>
+
+___END;
diff --git a/views/failsafe/install/pages/admin.php b/views/failsafe/install/pages/admin.php
new file mode 100644
index 000000000..1fdd5dced
--- /dev/null
+++ b/views/failsafe/install/pages/admin.php
@@ -0,0 +1,8 @@
+<?php
+/**
+ * Install create admin account page
+ */
+
+echo autop(elgg_echo('install:admin:instructions'));
+
+echo elgg_view('install/forms/admin', $vars);
diff --git a/views/failsafe/install/pages/complete.php b/views/failsafe/install/pages/complete.php
new file mode 100644
index 000000000..60838a630
--- /dev/null
+++ b/views/failsafe/install/pages/complete.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * Install completion page
+ */
+
+echo autop(elgg_echo('install:complete:instructions'));
+
+?>
+
+<div class="install_nav">
+<?php
+ echo "<a href=\"{$vars['url']}index.php\">Go to site</a>";
+?>
+</div>
diff --git a/views/failsafe/install/pages/database.php b/views/failsafe/install/pages/database.php
new file mode 100644
index 000000000..7765c6e48
--- /dev/null
+++ b/views/failsafe/install/pages/database.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * Install database page
+ *
+ * @uses $vars['failure'] Settings file exists but something went wrong
+ */
+
+if (isset($vars['failure']) && $vars['failure']) {
+ echo autop(elgg_echo('install:database:error'));
+ $vars['refresh'] = TRUE;
+ $vars['advance'] = FALSE;
+ echo elgg_view('install/nav', $vars);
+} else {
+ echo autop(elgg_echo('install:database:instructions'));
+ echo elgg_view('install/forms/database', $vars);
+} \ No newline at end of file
diff --git a/views/failsafe/install/pages/requirements.php b/views/failsafe/install/pages/requirements.php
new file mode 100644
index 000000000..b6516840f
--- /dev/null
+++ b/views/failsafe/install/pages/requirements.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Install requirements checking page
+ *
+ * @uses $vars['num_failures] Number of requirements failures
+ * @uses $vars['num_warnings] Number of recommendation warnings
+ */
+
+if ($vars['num_failures'] != 0) {
+ $instruct_text = elgg_echo('install:requirements:instructions:failure');
+} elseif ($vars['num_warnings'] != 0) {
+ $instruct_text = elgg_echo('install:requirements:instructions:warning');
+} else {
+ $instruct_text = elgg_echo('install:requirements:instructions:success');
+}
+
+echo autop($instruct_text);
+
+$report = $vars['report'];
+foreach ($report as $category => $checks) {
+ $title = elgg_echo("install:require:$category");
+ echo "<h3>$title</h3>";
+ echo "<ul>";
+ foreach ($checks as $check) {
+ echo "<li class=\"{$check['severity']}\">";
+ echo autop($check['message']);
+ echo "</li>";
+ }
+ echo "</ul>";
+}
+
+$vars['refresh'] = TRUE;
+
+// cannot advance to next step with a failure
+if ($vars['num_failures'] != 0) {
+ $vars['advance'] = FALSE;
+}
+
+echo elgg_view('install/nav', $vars);
diff --git a/views/failsafe/install/pages/settings.php b/views/failsafe/install/pages/settings.php
new file mode 100644
index 000000000..6f20573ef
--- /dev/null
+++ b/views/failsafe/install/pages/settings.php
@@ -0,0 +1,5 @@
+<?php
+
+echo autop(elgg_echo('install:settings:instructions'));
+
+echo elgg_view('install/forms/settings', $vars);
diff --git a/views/failsafe/install/pages/welcome.php b/views/failsafe/install/pages/welcome.php
new file mode 100644
index 000000000..f069e4ba7
--- /dev/null
+++ b/views/failsafe/install/pages/welcome.php
@@ -0,0 +1,8 @@
+<?php
+/**
+ * Install welcome page
+ */
+
+echo autop(elgg_echo('install:welcome:instructions'));
+
+echo elgg_view('install/nav', $vars);
diff --git a/views/failsafe/install/sidebar.php b/views/failsafe/install/sidebar.php
new file mode 100644
index 000000000..8136cd898
--- /dev/null
+++ b/views/failsafe/install/sidebar.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Install sidebar
+ *
+ * @uses $vars['step'] Current step
+ * @uses $vars['steps'] Array of steps
+ */
+
+$current_step = $vars['step'];
+$steps = $vars['steps'];
+
+$current_step_index = array_search($current_step, $steps);
+
+echo '<ol>';
+foreach ($steps as $index => $step) {
+ if ($index < $current_step_index) {
+ $class = 'past';
+ } elseif ($index == $current_step_index) {
+ $class = 'present';
+ } else {
+ $class = 'future';
+ }
+ $text = elgg_echo("install:$step");
+ echo "<li class=\"$class\">$text</li>";
+}
+echo '</ol>';
diff --git a/views/failsafe/page_shells/install.php b/views/failsafe/page_shells/install.php
new file mode 100644
index 000000000..b023197fa
--- /dev/null
+++ b/views/failsafe/page_shells/install.php
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Elgg install pageshell
+ *
+ * @package Elgg
+ * @subpackage Core
+ * @author Curverider Ltd
+ * @link http://elgg.org/
+ *
+ * @uses $vars['title'] The page title
+ * @uses $vars['body'] The main content of the page
+ * @uses $vars['sysmessages'] Array of system status messages
+ */
+
+// we won't trust server configuration but specify utf-8
+header('Content-type: text/html; charset=utf-8');
+
+// turn off browser caching
+header('Pragma: public', TRUE);
+header("Cache-Control: no-cache, must-revalidate", TRUE);
+header('Expires: Fri, 05 Feb 1982 00:00:00 -0500', TRUE);
+
+?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>Elgg Install : <?php echo $vars['title']; ?></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ <link rel="SHORTCUT ICON" href="<?php echo $vars['url']; ?>_graphics/favicon.ico" />
+ <link rel="stylesheet" href="<?php echo $vars['url']; ?>install/install.css" type="text/css" />
+ </head>
+ <body>
+ <div id="elgg_wrapper">
+ <div id="elgg_header">
+ <?php echo elgg_view('install/header', $vars); ?>
+ </div>
+ <div id="elgg_sidebar">
+ <?php echo elgg_view('install/sidebar', $vars); ?>
+ </div>
+ <div id="elgg_content">
+ <h2><?php echo $vars['title']; ?></h2>
+ <?php echo elgg_view('messages/list', array('object' => $vars['sysmessages'])); ?>
+ <?php echo $vars['body']; ?>
+ </div>
+ <div class="clearfloat"></div>
+ </div>
+ <div id="elgg_footer">
+ <?php echo elgg_view('install/footer'); ?>
+ </div>
+ </body>
+</html>