Elgg  Version 1.9
ElggInstaller.php
Go to the documentation of this file.
1 <?php
2 
31 
32  protected $steps = array(
33  'welcome',
34  'requirements',
35  'database',
36  'settings',
37  'admin',
38  'complete',
39  );
40 
41  protected $status = array(
42  'config' => FALSE,
43  'database' => FALSE,
44  'settings' => FALSE,
45  'admin' => FALSE,
46  );
47 
48  protected $isAction = FALSE;
49 
50  protected $autoLogin = TRUE;
51 
55  public function __construct() {
56  // load ElggRewriteTester as we depend on it
57  require_once(dirname(__FILE__) . "/ElggRewriteTester.php");
58 
59  $this->isAction = isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST';
60 
61  $this->bootstrapConfig();
62 
63  $this->bootstrapEngine();
64 
65  _elgg_services()->setValue('session', new ElggSession(new Elgg_Http_MockSessionStorage()));
66 
67  elgg_set_viewtype('installation');
68 
69  set_error_handler('_elgg_php_error_handler');
70  set_exception_handler('_elgg_php_exception_handler');
71 
72  register_translations(dirname(__FILE__) . '/languages/', TRUE);
73  }
74 
83  public function run($step) {
84  global $CONFIG;
85 
86  // language needs to be set before the first call to elgg_echo()
87  $CONFIG->language = 'en';
88 
89  // check if this is a URL rewrite test coming in
90  $this->processRewriteTest();
91 
92  if (!in_array($step, $this->getSteps())) {
93  $msg = elgg_echo('InstallationException:UnknownStep', array($step));
94  throw new InstallationException($msg);
95  }
96 
97  $this->setInstallStatus();
98 
100 
101  // check if this is an install being resumed
102  $this->resumeInstall($step);
103 
104  $this->finishBootstraping($step);
105 
106  $params = $this->getPostVariables();
107  $this->$step($params);
108  }
109 
117  public function setAutoLogin($flag) {
118  $this->autoLogin = (bool) $flag;
119  }
120 
139  public function batchInstall(array $params, $createHtaccess = FALSE) {
140  global $CONFIG;
141 
142  restore_error_handler();
143  restore_exception_handler();
144 
145  $defaults = array(
146  'dbhost' => 'localhost',
147  'dbprefix' => 'elgg_',
148  'path' => $CONFIG->path,
149  'language' => 'en',
150  'siteaccess' => ACCESS_PUBLIC,
151  );
152  $params = array_merge($defaults, $params);
153 
154  $requiredParams = array(
155  'dbuser',
156  'dbpassword',
157  'dbname',
158  'sitename',
159  'wwwroot',
160  'dataroot',
161  'displayname',
162  'email',
163  'username',
164  'password',
165  );
166  foreach ($requiredParams as $key) {
167  if (empty($params[$key])) {
168  $msg = elgg_echo('install:error:requiredfield', array($key));
169  throw new InstallationException($msg);
170  }
171  }
172 
173  // password is passed in once
174  $params['password1'] = $params['password2'] = $params['password'];
175 
176  if ($createHtaccess) {
177  $rewriteTester = new ElggRewriteTester();
178  if (!$rewriteTester->createHtaccess($params['wwwroot'], $CONFIG->path)) {
179  throw new InstallationException(elgg_echo('install:error:htaccess'));
180  }
181  }
182 
183  $this->setInstallStatus();
184 
185  if (!$this->status['config']) {
186  if (!$this->createSettingsFile($params)) {
187  throw new InstallationException(elgg_echo('install:error:settings'));
188  }
189  }
190 
191  if (!$this->connectToDatabase()) {
192  throw new InstallationException(elgg_echo('install:error:databasesettings'));
193  }
194 
195  if (!$this->status['database']) {
196  if (!$this->installDatabase()) {
197  throw new InstallationException(elgg_echo('install:error:cannotloadtables'));
198  }
199  }
200 
201  // load remaining core libraries
202  $this->finishBootstraping('settings');
203 
204  if (!$this->saveSiteSettings($params)) {
205  throw new InstallationException(elgg_echo('install:error:savesitesettings'));
206  }
207 
208  if (!$this->createAdminAccount($params)) {
209  throw new InstallationException(elgg_echo('install:admin:cannot_create'));
210  }
211  }
212 
221  protected function render($step, $vars = array()) {
222 
223  $vars['next_step'] = $this->getNextStep($step);
224 
225  $title = elgg_echo("install:$step");
226  $body = elgg_view("install/pages/$step", $vars);
227  echo elgg_view_page(
228  $title,
229  $body,
230  'default',
231  array(
232  'step' => $step,
233  'steps' => $this->getSteps(),
234  )
235  );
236  exit;
237  }
238 
250  protected function welcome($vars) {
251  $this->render('welcome');
252  }
253 
263  protected function requirements($vars) {
264 
265  $report = array();
266 
267  // check PHP parameters and libraries
268  $this->checkPHP($report);
269 
270  // check URL rewriting
271  $this->checkRewriteRules($report);
272 
273  // check for existence of settings file
274  if ($this->checkSettingsFile($report) != TRUE) {
275  // no file, so check permissions on engine directory
276  $this->checkEngineDir($report);
277  }
278 
279  // check the database later
280  $report['database'] = array(array(
281  'severity' => 'info',
282  'message' => elgg_echo('install:check:database')
283  ));
284 
285  // any failures?
286  $numFailures = $this->countNumConditions($report, 'failure');
287 
288  // any warnings
289  $numWarnings = $this->countNumConditions($report, 'warning');
290 
291 
292  $params = array(
293  'report' => $report,
294  'num_failures' => $numFailures,
295  'num_warnings' => $numWarnings,
296  );
297 
298  $this->render('requirements', $params);
299  }
300 
310  protected function database($submissionVars) {
311 
312  $formVars = array(
313  'dbuser' => array(
314  'type' => 'text',
315  'value' => '',
316  'required' => TRUE,
317  ),
318  'dbpassword' => array(
319  'type' => 'password',
320  'value' => '',
321  'required' => FALSE,
322  ),
323  'dbname' => array(
324  'type' => 'text',
325  'value' => '',
326  'required' => TRUE,
327  ),
328  'dbhost' => array(
329  'type' => 'text',
330  'value' => 'localhost',
331  'required' => TRUE,
332  ),
333  'dbprefix' => array(
334  'type' => 'text',
335  'value' => 'elgg_',
336  'required' => TRUE,
337  ),
338  );
339 
340  if ($this->checkSettingsFile()) {
341  // user manually created settings file so we fake out action test
342  $this->isAction = TRUE;
343  }
344 
345  if ($this->isAction) {
346  do {
347  // only create settings file if it doesn't exist
348  if (!$this->checkSettingsFile()) {
349  if (!$this->validateDatabaseVars($submissionVars, $formVars)) {
350  // error so we break out of action and serve same page
351  break;
352  }
353 
354  if (!$this->createSettingsFile($submissionVars)) {
355  break;
356  }
357  }
358 
359  // check db version and connect
360  if (!$this->connectToDatabase()) {
361  break;
362  }
363 
364  if (!$this->installDatabase()) {
365  break;
366  }
367 
368  system_message(elgg_echo('install:success:database'));
369 
370  $this->continueToNextStep('database');
371  } while (FALSE); // PHP doesn't support breaking out of if statements
372  }
373 
374  $formVars = $this->makeFormSticky($formVars, $submissionVars);
375 
376  $params = array('variables' => $formVars,);
377 
378  if ($this->checkSettingsFile()) {
379  // settings file exists and we're here so failed to create database
380  $params['failure'] = TRUE;
381  }
382 
383  $this->render('database', $params);
384  }
385 
395  protected function settings($submissionVars) {
396  global $CONFIG;
397 
398  $formVars = array(
399  'sitename' => array(
400  'type' => 'text',
401  'value' => 'My New Community',
402  'required' => TRUE,
403  ),
404  'siteemail' => array(
405  'type' => 'email',
406  'value' => '',
407  'required' => FALSE,
408  ),
409  'wwwroot' => array(
410  'type' => 'url',
411  'value' => elgg_get_site_url(),
412  'required' => TRUE,
413  ),
414  'path' => array(
415  'type' => 'text',
416  'value' => $CONFIG->path,
417  'required' => TRUE,
418  ),
419  'dataroot' => array(
420  'type' => 'text',
421  'value' => '',
422  'required' => TRUE,
423  ),
424  'siteaccess' => array(
425  'type' => 'access',
426  'value' => ACCESS_PUBLIC,
427  'required' => TRUE,
428  ),
429  );
430 
431  // if Apache, we give user option of having Elgg create data directory
432  //if (ElggRewriteTester::guessWebServer() == 'apache') {
433  // $formVars['dataroot']['type'] = 'combo';
434  // $CONFIG->translations['en']['install:settings:help:dataroot'] =
435  // $CONFIG->translations['en']['install:settings:help:dataroot:apache'];
436  //}
437 
438  if ($this->isAction) {
439  do {
440  //if (!$this->createDataDirectory($submissionVars, $formVars)) {
441  // break;
442  //}
443 
444  if (!$this->validateSettingsVars($submissionVars, $formVars)) {
445  break;
446  }
447 
448  if (!$this->saveSiteSettings($submissionVars)) {
449  break;
450  }
451 
452  system_message(elgg_echo('install:success:settings'));
453 
454  $this->continueToNextStep('settings');
455 
456  } while (FALSE); // PHP doesn't support breaking out of if statements
457  }
458 
459  $formVars = $this->makeFormSticky($formVars, $submissionVars);
460 
461  $this->render('settings', array('variables' => $formVars));
462  }
463 
473  protected function admin($submissionVars) {
474  $formVars = array(
475  'displayname' => array(
476  'type' => 'text',
477  'value' => '',
478  'required' => TRUE,
479  ),
480  'email' => array(
481  'type' => 'email',
482  'value' => '',
483  'required' => TRUE,
484  ),
485  'username' => array(
486  'type' => 'text',
487  'value' => '',
488  'required' => TRUE,
489  ),
490  'password1' => array(
491  'type' => 'password',
492  'value' => '',
493  'required' => TRUE,
494  'pattern' => '.{6,}',
495  ),
496  'password2' => array(
497  'type' => 'password',
498  'value' => '',
499  'required' => TRUE,
500  ),
501  );
502 
503  if ($this->isAction) {
504  do {
505  if (!$this->validateAdminVars($submissionVars, $formVars)) {
506  break;
507  }
508 
509  if (!$this->createAdminAccount($submissionVars, $this->autoLogin)) {
510  break;
511  }
512 
513  system_message(elgg_echo('install:success:admin'));
514 
515  $this->continueToNextStep('admin');
516 
517  } while (FALSE); // PHP doesn't support breaking out of if statements
518  }
519 
520  // bit of a hack to get the password help to show right number of characters
521  global $CONFIG;
523  $CONFIG->translations[$lang]['install:admin:help:password1'] =
524  sprintf($CONFIG->translations[$lang]['install:admin:help:password1'],
525  $CONFIG->min_password_length);
526 
527  $formVars = $this->makeFormSticky($formVars, $submissionVars);
528 
529  $this->render('admin', array('variables' => $formVars));
530  }
531 
537  protected function complete() {
538 
539  $params = array();
540  if ($this->autoLogin) {
541  $params['destination'] = 'admin';
542  } else {
543  $params['destination'] = 'index.php';
544  }
545 
546  $this->render('complete', $params);
547  }
548 
558  protected function getSteps() {
559  return $this->steps;
560  }
561 
569  protected function continueToNextStep($currentStep) {
570  $this->isAction = FALSE;
571  forward($this->getNextStepUrl($currentStep));
572  }
573 
581  protected function getNextStep($currentStep) {
582  $index = 1 + array_search($currentStep, $this->steps);
583  if (isset($this->steps[$index])) {
584  return $this->steps[$index];
585  } else {
586  return null;
587  }
588  }
589 
597  protected function getNextStepUrl($currentStep) {
598  $nextStep = $this->getNextStep($currentStep);
599  return elgg_get_site_url() . "install.php?step=$nextStep";
600  }
601 
608  protected function setInstallStatus() {
609  global $CONFIG;
610 
611  if (!is_readable("{$CONFIG->path}engine/settings.php")) {
612  return;
613  }
614 
615  $this->loadSettingsFile();
616 
617  $this->status['config'] = TRUE;
618 
619  // must be able to connect to database to jump install steps
620  $dbSettingsPass = $this->checkDatabaseSettings(
621  $CONFIG->dbuser,
622  $CONFIG->dbpass,
623  $CONFIG->dbname,
624  $CONFIG->dbhost
625  );
626  if ($dbSettingsPass == FALSE) {
627  return;
628  }
629 
630  if (!include_once("{$CONFIG->path}engine/lib/database.php")) {
631  throw new InstallationException(elgg_echo('InstallationException:MissingLibrary', array('database.php')));
632  }
633 
634  // check that the config table has been created
635  $query = "show tables";
636  $result = get_data($query);
637  if ($result) {
638  foreach ($result as $table) {
639  $table = (array) $table;
640  if (in_array("{$CONFIG->dbprefix}config", $table)) {
641  $this->status['database'] = TRUE;
642  }
643  }
644  if ($this->status['database'] == FALSE) {
645  return;
646  }
647  } else {
648  // no tables
649  return;
650  }
651 
652  // check that the config table has entries
653  $query = "SELECT COUNT(*) AS total FROM {$CONFIG->dbprefix}config";
654  $result = get_data($query);
655  if ($result && $result[0]->total > 0) {
656  $this->status['settings'] = TRUE;
657  } else {
658  return;
659  }
660 
661  // check that the users entity table has an entry
662  $query = "SELECT COUNT(*) AS total FROM {$CONFIG->dbprefix}users_entity";
663  $result = get_data($query);
664  if ($result && $result[0]->total > 0) {
665  $this->status['admin'] = TRUE;
666  } else {
667  return;
668  }
669  }
670 
679  protected function checkInstallCompletion($step) {
680  if ($step != 'complete') {
681  if (!in_array(FALSE, $this->status)) {
682  // install complete but someone is trying to view an install page
683  forward();
684  }
685  }
686  }
687 
696  protected function resumeInstall($step) {
697  // only do a resume from the first step
698  if ($step !== 'welcome') {
699  return;
700  }
701 
702  if ($this->status['database'] == FALSE) {
703  return;
704  }
705 
706  if ($this->status['settings'] == FALSE) {
707  forward("install.php?step=settings");
708  }
709 
710  if ($this->status['admin'] == FALSE) {
711  forward("install.php?step=admin");
712  }
713 
714  // everything appears to be set up
715  forward("install.php?step=complete");
716  }
717 
727  protected function bootstrapEngine() {
728  global $CONFIG;
729 
730  $lib_dir = $CONFIG->path . 'engine/lib/';
731 
732  // bootstrapping with required files in a required order
733  $required_files = array(
734  'autoloader.php',
735  'elgglib.php',
736  'views.php',
737  'access.php',
738  'system_log.php',
739  'configuration.php',
740  'database.php',
741  'sessions.php',
742  'languages.php',
743  'pageowner.php',
744  'input.php',
745  'cache.php',
746  'output.php',
747  );
748 
749  foreach ($required_files as $file) {
750  $path = $lib_dir . $file;
751  if (!include($path)) {
752  echo "Could not load file '$path'. "
753  . 'Please check your Elgg installation for all required files.';
754  exit;
755  }
756  }
757  }
758 
768  protected function finishBootstraping($step) {
769 
770  $dbIndex = array_search('database', $this->getSteps());
771  $settingsIndex = array_search('settings', $this->getSteps());
772  $adminIndex = array_search('admin', $this->getSteps());
773  $completeIndex = array_search('complete', $this->getSteps());
774  $stepIndex = array_search($step, $this->getSteps());
775 
776  // To log in the user, we need to use the Elgg core session handling.
777  // Otherwise, use default php session handling
778  $useElggSession = ($stepIndex == $adminIndex && $this->isAction) ||
779  $stepIndex == $completeIndex;
780  if (!$useElggSession) {
781  session_name('Elgg_install');
782  session_start();
783  elgg_unregister_event_handler('boot', 'system', 'session_init');
784  }
785 
786  if ($stepIndex > $dbIndex) {
787  // once the database has been created, load rest of engine
788  global $CONFIG;
789  $lib_dir = $CONFIG->path . 'engine/lib/';
790 
791  $this->loadSettingsFile();
792 
793  $lib_files = array(
794  // these want to be loaded first apparently?
795  'autoloader.php',
796  'database.php',
797  'actions.php',
798 
799  'admin.php',
800  'annotations.php',
801  'cron.php',
802  'entities.php',
803  'extender.php',
804  'filestore.php',
805  'group.php',
806  'mb_wrapper.php',
807  'memcache.php',
808  'metadata.php',
809  'metastrings.php',
810  'navigation.php',
811  'notification.php',
812  'objects.php',
813  'pagehandler.php',
814  'pam.php',
815  'plugins.php',
816  'private_settings.php',
817  'relationships.php',
818  'river.php',
819  'sites.php',
820  'statistics.php',
821  'tags.php',
822  'user_settings.php',
823  'users.php',
824  'upgrade.php',
825  'widgets.php',
826  'deprecated-1.7.php',
827  'deprecated-1.8.php',
828  'deprecated-1.9.php',
829  );
830 
831  foreach ($lib_files as $file) {
832  $path = $lib_dir . $file;
833  if (!include_once($path)) {
834  throw new InstallationException('InstallationException:MissingLibrary', array($file));
835  }
836  }
837 
838  _elgg_services()->db->setupConnections();
839  register_translations(dirname(dirname(__FILE__)) . "/languages/");
840 
841  if ($stepIndex > $settingsIndex) {
842  $CONFIG->site_guid = (int) datalist_get('default_site');
843  $CONFIG->site_id = $CONFIG->site_guid;
844  $CONFIG->site = get_entity($CONFIG->site_guid);
845  $CONFIG->dataroot = datalist_get('dataroot');
847  }
848 
849  elgg_trigger_event('init', 'system');
850  }
851  }
852 
858  protected function bootstrapConfig() {
859  global $CONFIG;
860  if (!isset($CONFIG)) {
861  $CONFIG = new stdClass;
862  }
863 
864  $CONFIG->wwwroot = $this->getBaseUrl();
865  $CONFIG->url = $CONFIG->wwwroot;
866  $CONFIG->path = dirname(dirname(__FILE__)) . '/';
867  $CONFIG->viewpath = $CONFIG->path . 'views/';
868  $CONFIG->pluginspath = $CONFIG->path . 'mod/';
869  $CONFIG->context = array();
870  $CONFIG->entity_types = array('group', 'object', 'site', 'user');
871  // required by elgg_view_page()
872  $CONFIG->sitename = '';
873  $CONFIG->sitedescription = '';
874  }
875 
879  private function isHttps() {
880  return (!empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") ||
881  $_SERVER['SERVER_PORT'] == 443;
882  }
883 
892  protected function getBaseUrl() {
893  $protocol = $this->isHttps() ? 'https' : 'http';
894 
895  if (isset($_SERVER["SERVER_PORT"])) {
896  $port = ':' . $_SERVER["SERVER_PORT"];
897  } else {
898  $port = '';
899  }
900  if ($port == ':80' || $port == ':443') {
901  $port = '';
902  }
903  $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
904  $cutoff = strpos($uri, 'install.php');
905  $uri = substr($uri, 0, $cutoff);
906  $serverName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
907 
908  return "$protocol://{$serverName}$port{$uri}";
909  }
910 
917  protected function loadSettingsFile() {
918  global $CONFIG;
919 
920  if (!include_once("{$CONFIG->path}engine/settings.php")) {
921  throw new InstallationException(elgg_echo('InstallationException:CannotLoadSettings'));
922  }
923  }
924 
938  protected function getPostVariables() {
939  $vars = array();
940  foreach ($_POST as $k => $v) {
941  $vars[$k] = $v;
942  }
943  return $vars;
944  }
945 
954  protected function makeFormSticky($formVars, $submissionVars) {
955  foreach ($submissionVars as $field => $value) {
956  $formVars[$field]['value'] = $value;
957  }
958  return $formVars;
959  }
960 
972  protected function checkEngineDir(&$report) {
973  global $CONFIG;
974 
975  $writable = is_writable("{$CONFIG->path}engine");
976  if (!$writable) {
977  $report['settings'] = array(
978  array(
979  'severity' => 'failure',
980  'message' => elgg_echo('install:check:enginedir'),
981  )
982  );
983  return FALSE;
984  }
985 
986  return TRUE;
987  }
988 
996  protected function checkSettingsFile(&$report = array()) {
997  global $CONFIG;
998 
999  if (!file_exists("{$CONFIG->path}engine/settings.php")) {
1000  return FALSE;
1001  }
1002 
1003  if (!is_readable("{$CONFIG->path}engine/settings.php")) {
1004  $report['settings'] = array(
1005  array(
1006  'severity' => 'failure',
1007  'message' => elgg_echo('install:check:readsettings'),
1008  )
1009  );
1010  }
1011 
1012  return TRUE;
1013  }
1014 
1022  protected function checkPHP(&$report) {
1023  $phpReport = array();
1024 
1025  $elgg_php_version = '5.2.0';
1026  if (version_compare(PHP_VERSION, $elgg_php_version, '<')) {
1027  $phpReport[] = array(
1028  'severity' => 'failure',
1029  'message' => elgg_echo('install:check:php:version', array($elgg_php_version, PHP_VERSION))
1030  );
1031  }
1032 
1033  $this->checkPhpExtensions($phpReport);
1034 
1035  $this->checkPhpDirectives($phpReport);
1036 
1037  if (count($phpReport) == 0) {
1038  $phpReport[] = array(
1039  'severity' => 'pass',
1040  'message' => elgg_echo('install:check:php:success')
1041  );
1042  }
1043 
1044  $report['php'] = $phpReport;
1045  }
1046 
1054  protected function checkPhpExtensions(&$phpReport) {
1055  $extensions = get_loaded_extensions();
1056  $requiredExtensions = array(
1057  'mysql',
1058  'json',
1059  'xml',
1060  'gd',
1061  );
1062  foreach ($requiredExtensions as $extension) {
1063  if (!in_array($extension, $extensions)) {
1064  $phpReport[] = array(
1065  'severity' => 'failure',
1066  'message' => elgg_echo('install:check:php:extension', array($extension))
1067  );
1068  }
1069  }
1070 
1071  $recommendedExtensions = array(
1072  'mbstring',
1073  );
1074  foreach ($recommendedExtensions as $extension) {
1075  if (!in_array($extension, $extensions)) {
1076  $phpReport[] = array(
1077  'severity' => 'warning',
1078  'message' => elgg_echo('install:check:php:extension:recommend', array($extension))
1079  );
1080  }
1081  }
1082  }
1083 
1091  protected function checkPhpDirectives(&$phpReport) {
1092  if (ini_get('open_basedir')) {
1093  $phpReport[] = array(
1094  'severity' => 'warning',
1095  'message' => elgg_echo("install:check:php:open_basedir")
1096  );
1097  }
1098 
1099  if (ini_get('safe_mode')) {
1100  $phpReport[] = array(
1101  'severity' => 'warning',
1102  'message' => elgg_echo("install:check:php:safe_mode")
1103  );
1104  }
1105 
1106  if (ini_get('arg_separator.output') !== '&') {
1107  $separator = htmlspecialchars(ini_get('arg_separator.output'));
1108  $msg = elgg_echo("install:check:php:arg_separator", array($separator));
1109  $phpReport[] = array(
1110  'severity' => 'failure',
1111  'message' => $msg,
1112  );
1113  }
1114 
1115  if (ini_get('register_globals')) {
1116  $phpReport[] = array(
1117  'severity' => 'failure',
1118  'message' => elgg_echo("install:check:php:register_globals")
1119  );
1120  }
1121 
1122  if (ini_get('session.auto_start')) {
1123  $phpReport[] = array(
1124  'severity' => 'failure',
1125  'message' => elgg_echo("install:check:php:session.auto_start")
1126  );
1127  }
1128  }
1129 
1137  protected function checkRewriteRules(&$report) {
1138  global $CONFIG;
1139 
1140  $tester = new ElggRewriteTester();
1141  $url = elgg_get_site_url() . "rewrite.php";
1142  $report['rewrite'] = array($tester->run($url, $CONFIG->path));
1143  }
1144 
1151  protected function processRewriteTest() {
1152  if (strpos($_SERVER['REQUEST_URI'], 'rewrite.php') !== FALSE) {
1153  echo 'success';
1154  exit;
1155  }
1156  }
1157 
1166  protected function countNumConditions($report, $condition) {
1167  $count = 0;
1168  foreach ($report as $category => $checks) {
1169  foreach ($checks as $check) {
1170  if ($check['severity'] === $condition) {
1171  $count++;
1172  }
1173  }
1174  }
1175 
1176  return $count;
1177  }
1178 
1179 
1192  protected function validateDatabaseVars($submissionVars, $formVars) {
1193 
1194  foreach ($formVars as $field => $info) {
1195  if ($info['required'] == TRUE && !$submissionVars[$field]) {
1196  $name = elgg_echo("install:database:label:$field");
1197  register_error(elgg_echo('install:error:requiredfield', array($name)));
1198  return FALSE;
1199  }
1200  }
1201 
1202  // according to postgres documentation: SQL identifiers and key words must
1203  // begin with a letter (a-z, but also letters with diacritical marks and
1204  // non-Latin letters) or an underscore (_). Subsequent characters in an
1205  // identifier or key word can be letters, underscores, digits (0-9), or dollar signs ($).
1206  // Refs #4994
1207  if (!preg_match("/^[a-zA-Z_][\w]*$/", $submissionVars['dbprefix'])) {
1208  register_error(elgg_echo('install:error:database_prefix'));
1209  return FALSE;
1210  }
1211 
1212  return $this->checkDatabaseSettings(
1213  $submissionVars['dbuser'],
1214  $submissionVars['dbpassword'],
1215  $submissionVars['dbname'],
1216  $submissionVars['dbhost']
1217  );
1218  }
1219 
1230  protected function checkDatabaseSettings($user, $password, $dbname, $host) {
1231  $mysql_dblink = mysql_connect($host, $user, $password, true);
1232  if ($mysql_dblink == FALSE) {
1233  register_error(elgg_echo('install:error:databasesettings'));
1234  return FALSE;
1235  }
1236 
1237  $result = mysql_select_db($dbname, $mysql_dblink);
1238 
1239  // check MySQL version - must be 5.0 or >
1240  $required_version = 5.0;
1241  $version = mysql_get_server_info();
1242  $points = explode('.', $version);
1243  if ($points[0] < $required_version) {
1244  register_error(elgg_echo('install:error:oldmysql', array($version)));
1245  return FALSE;
1246  }
1247 
1248  mysql_close($mysql_dblink);
1249 
1250  if (!$result) {
1251  register_error(elgg_echo('install:error:nodatabase', array($dbname)));
1252  }
1253 
1254  return $result;
1255  }
1256 
1264  protected function createSettingsFile($params) {
1265  global $CONFIG;
1266 
1267  $templateFile = "{$CONFIG->path}engine/settings.example.php";
1268  $template = file_get_contents($templateFile);
1269  if (!$template) {
1270  register_error(elgg_echo('install:error:readsettingsphp'));
1271  return FALSE;
1272  }
1273 
1274  foreach ($params as $k => $v) {
1275  $template = str_replace("{{" . $k . "}}", $v, $template);
1276  }
1277 
1278  $settingsFilename = "{$CONFIG->path}engine/settings.php";
1279  $result = file_put_contents($settingsFilename, $template);
1280  if (!$result) {
1281  register_error(elgg_echo('install:error:writesettingphp'));
1282  return FALSE;
1283  }
1284 
1285  return TRUE;
1286  }
1287 
1293  protected function connectToDatabase() {
1294  global $CONFIG;
1295 
1296  if (!include_once("{$CONFIG->path}engine/settings.php")) {
1297  register_error('Elgg could not load the settings file. It does not exist or there is a file permissions issue.');
1298  return FALSE;
1299  }
1300 
1301  if (!include_once("{$CONFIG->path}engine/lib/database.php")) {
1302  register_error('Could not load database.php');
1303  return FALSE;
1304  }
1305 
1306  try {
1307  _elgg_services()->db->setupConnections();
1308  } catch (DatabaseException $e) {
1309  register_error($e->getMessage());
1310  return FALSE;
1311  }
1312 
1313  return TRUE;
1314  }
1315 
1321  protected function installDatabase() {
1322  global $CONFIG;
1323 
1324  try {
1325  run_sql_script("{$CONFIG->path}engine/schema/mysql.sql");
1326  } catch (Exception $e) {
1327  $msg = $e->getMessage();
1328  if (strpos($msg, 'already exists')) {
1329  $msg = elgg_echo('install:error:tables_exist');
1330  }
1331  register_error($msg);
1332  return FALSE;
1333  }
1334 
1335  return TRUE;
1336  }
1337 
1349  protected function createDataDirectory(&$submissionVars, $formVars) {
1350  // did the user have option of Elgg creating the data directory
1351  if ($formVars['dataroot']['type'] != 'combo') {
1352  return TRUE;
1353  }
1354 
1355  // did the user select the option
1356  if ($submissionVars['dataroot'] != 'dataroot-checkbox') {
1357  return TRUE;
1358  }
1359 
1360  $dir = sanitise_filepath($submissionVars['path']) . 'data';
1361  if (file_exists($dir) || mkdir($dir, 0700)) {
1362  $submissionVars['dataroot'] = $dir;
1363  if (!file_exists("$dir/.htaccess")) {
1364  $htaccess = "Order Deny,Allow\nDeny from All\n";
1365  if (!file_put_contents("$dir/.htaccess", $htaccess)) {
1366  return FALSE;
1367  }
1368  }
1369  return TRUE;
1370  }
1371 
1372  return FALSE;
1373  }
1374 
1383  protected function validateSettingsVars($submissionVars, $formVars) {
1384  global $CONFIG;
1385 
1386  foreach ($formVars as $field => $info) {
1387  $submissionVars[$field] = trim($submissionVars[$field]);
1388  if ($info['required'] == TRUE && $submissionVars[$field] === '') {
1389  $name = elgg_echo("install:settings:label:$field");
1390  register_error(elgg_echo('install:error:requiredfield', array($name)));
1391  return FALSE;
1392  }
1393  }
1394 
1395  // check that data root is absolute path
1396  if (stripos(PHP_OS, 'win') === 0) {
1397  if (strpos($submissionVars['dataroot'], ':') !== 1) {
1398  $msg = elgg_echo('install:error:relative_path', array($submissionVars['dataroot']));
1399  register_error($msg);
1400  return FALSE;
1401  }
1402  } else {
1403  if (strpos($submissionVars['dataroot'], '/') !== 0) {
1404  $msg = elgg_echo('install:error:relative_path', array($submissionVars['dataroot']));
1405  register_error($msg);
1406  return FALSE;
1407  }
1408  }
1409 
1410  // check that data root exists
1411  if (!file_exists($submissionVars['dataroot'])) {
1412  $msg = elgg_echo('install:error:datadirectoryexists', array($submissionVars['dataroot']));
1413  register_error($msg);
1414  return FALSE;
1415  }
1416 
1417  // check that data root is writable
1418  if (!is_writable($submissionVars['dataroot'])) {
1419  $msg = elgg_echo('install:error:writedatadirectory', array($submissionVars['dataroot']));
1420  register_error($msg);
1421  return FALSE;
1422  }
1423 
1424  if (!isset($CONFIG->data_dir_override) || !$CONFIG->data_dir_override) {
1425  // check that data root is not subdirectory of Elgg root
1426  if (stripos($submissionVars['dataroot'], $submissionVars['path']) === 0) {
1427  $msg = elgg_echo('install:error:locationdatadirectory', array($submissionVars['dataroot']));
1428  register_error($msg);
1429  return FALSE;
1430  }
1431  }
1432 
1433  // check that email address is email address
1434  if ($submissionVars['siteemail'] && !is_email_address($submissionVars['siteemail'])) {
1435  $msg = elgg_echo('install:error:emailaddress', array($submissionVars['siteemail']));
1436  register_error($msg);
1437  return FALSE;
1438  }
1439 
1440  // @todo check that url is a url
1441  // @note filter_var cannot be used because it doesn't work on international urls
1442 
1443  return TRUE;
1444  }
1445 
1453  protected function saveSiteSettings($submissionVars) {
1454  global $CONFIG;
1455 
1456  // ensure that file path, data path, and www root end in /
1457  $submissionVars['path'] = sanitise_filepath($submissionVars['path']);
1458  $submissionVars['dataroot'] = sanitise_filepath($submissionVars['dataroot']);
1459  $submissionVars['wwwroot'] = sanitise_filepath($submissionVars['wwwroot']);
1460 
1461  $site = new ElggSite();
1462  $site->name = strip_tags($submissionVars['sitename']);
1463  $site->url = $submissionVars['wwwroot'];
1464  $site->access_id = ACCESS_PUBLIC;
1465  $site->email = $submissionVars['siteemail'];
1466  $guid = $site->save();
1467 
1468  if (!$guid) {
1469  register_error(elgg_echo('install:error:createsite'));
1470  return FALSE;
1471  }
1472 
1473  // bootstrap site info
1474  $CONFIG->site_guid = $guid;
1475  $CONFIG->site_id = $guid;
1476  $CONFIG->site = $site;
1477 
1478  datalist_set('installed', time());
1479  datalist_set('path', $submissionVars['path']);
1480  datalist_set('dataroot', $submissionVars['dataroot']);
1481  datalist_set('default_site', $site->getGUID());
1482  datalist_set('version', elgg_get_version());
1483  datalist_set('simplecache_enabled', 1);
1484  datalist_set('system_cache_enabled', 1);
1485  datalist_set('simplecache_lastupdate', time());
1486 
1487  // new installations have run all the upgrades
1488  $upgrades = elgg_get_upgrade_files($submissionVars['path'] . 'engine/lib/upgrades/');
1489  datalist_set('processed_upgrades', serialize($upgrades));
1490 
1491  set_config('view', 'default', $site->getGUID());
1492  set_config('language', 'en', $site->getGUID());
1493  set_config('default_access', $submissionVars['siteaccess'], $site->getGUID());
1494  set_config('allow_registration', TRUE, $site->getGUID());
1495  set_config('walled_garden', FALSE, $site->getGUID());
1496  set_config('allow_user_default_access', '', $site->getGUID());
1497 
1498  $this->setSubtypeClasses();
1499 
1500  $this->enablePlugins();
1501 
1502  return TRUE;
1503  }
1504 
1510  protected function setSubtypeClasses() {
1511  add_subtype("object", "plugin", "ElggPlugin");
1512  add_subtype("object", "file", "ElggFile");
1513  add_subtype("object", "widget", "ElggWidget");
1514  add_subtype("object", "comment", "ElggComment");
1515  add_subtype("object", "elgg_upgrade", 'ElggUpgrade');
1516  }
1517 
1523  protected function enablePlugins() {
1525  $plugins = elgg_get_plugins('any');
1526  foreach ($plugins as $plugin) {
1527  if ($plugin->getManifest()) {
1528  if ($plugin->getManifest()->getActivateOnInstall()) {
1529  $plugin->activate();
1530  }
1531  if (in_array('theme', $plugin->getManifest()->getCategories())) {
1532  $plugin->setPriority('last');
1533  }
1534  }
1535  }
1536  }
1537 
1550  protected function validateAdminVars($submissionVars, $formVars) {
1551 
1552  foreach ($formVars as $field => $info) {
1553  if ($info['required'] == TRUE && !$submissionVars[$field]) {
1554  $name = elgg_echo("install:admin:label:$field");
1555  register_error(elgg_echo('install:error:requiredfield', array($name)));
1556  return FALSE;
1557  }
1558  }
1559 
1560  if ($submissionVars['password1'] !== $submissionVars['password2']) {
1561  register_error(elgg_echo('install:admin:password:mismatch'));
1562  return FALSE;
1563  }
1564 
1565  if (trim($submissionVars['password1']) == "") {
1566  register_error(elgg_echo('install:admin:password:empty'));
1567  return FALSE;
1568  }
1569 
1570  $minLength = get_config('min_password_length');
1571  if (strlen($submissionVars['password1']) < $minLength) {
1572  register_error(elgg_echo('install:admin:password:tooshort'));
1573  return FALSE;
1574  }
1575 
1576  // check that email address is email address
1577  if ($submissionVars['email'] && !is_email_address($submissionVars['email'])) {
1578  $msg = elgg_echo('install:error:emailaddress', array($submissionVars['email']));
1579  register_error($msg);
1580  return FALSE;
1581  }
1582 
1583  return TRUE;
1584  }
1585 
1594  protected function createAdminAccount($submissionVars, $login = FALSE) {
1595  try {
1596  $guid = register_user(
1597  $submissionVars['username'],
1598  $submissionVars['password1'],
1599  $submissionVars['displayname'],
1600  $submissionVars['email']
1601  );
1602  } catch (Exception $e) {
1603  register_error($e->getMessage());
1604  return false;
1605  }
1606 
1607  if (!$guid) {
1608  register_error(elgg_echo('install:admin:cannot_create'));
1609  return false;
1610  }
1611 
1612  $user = get_entity($guid);
1613  if (!$user instanceof ElggUser) {
1614  register_error(elgg_echo('install:error:loadadmin'));
1615  return false;
1616  }
1617 
1618  elgg_set_ignore_access(TRUE);
1619  if ($user->makeAdmin() == FALSE) {
1620  register_error(elgg_echo('install:error:adminaccess'));
1621  } else {
1622  datalist_set('admin_registered', 1);
1623  }
1624  elgg_set_ignore_access(false);
1625 
1626  // add validation data to satisfy user validation plugins
1627  create_metadata($guid, 'validated', TRUE, '', 0, ACCESS_PUBLIC);
1628  create_metadata($guid, 'validated_method', 'admin_user', '', 0, ACCESS_PUBLIC);
1629 
1630  if ($login) {
1632  $storage = new Elgg_Http_NativeSessionStorage(array(), $handler);
1633  $session = new ElggSession($storage);
1634  $session->setName('Elgg');
1635  _elgg_services()->setValue('session', $session);
1636  if (login($user) == FALSE) {
1637  register_error(elgg_echo('install:error:adminlogin'));
1638  }
1639  }
1640 
1641  return TRUE;
1642  }
1643 }
$session
Definition: login.php:9
$password
Definition: login.php:25
$params
Definition: login.php:72
$handler
Definition: add.php:10
$title
Definition: save.php:24
$plugins
if($guid==elgg_get_logged_in_user_guid()) $name
Definition: delete.php:21
_elgg_services()
Definition: autoloader.php:14
$user
Definition: ban.php:13
checkDatabaseSettings($user, $password, $dbname, $host)
Confirm the settings for the database.
continueToNextStep($currentStep)
Forwards the browser to the next step.
makeFormSticky($formVars, $submissionVars)
If form is reshown, remember previously submitted variables.
checkPhpExtensions(&$phpReport)
Check the server's PHP extensions.
validateDatabaseVars($submissionVars, $formVars)
Database support methods.
setAutoLogin($flag)
Set the auto login flag.
getPostVariables()
Action handling methods.
getBaseUrl()
Get the best guess at the base URL.
checkInstallCompletion($step)
Security check to ensure the installer cannot be run after installation has finished.
welcome($vars)
Step controllers.
createDataDirectory(&$submissionVars, $formVars)
Site settings support methods.
render($step, $vars=array())
Renders the data passed by a controller.
finishBootstraping($step)
Load remaining engine libraries and complete bootstraping (see start.php)
saveSiteSettings($submissionVars)
Initialize the site including site entity, plugins, and configuration.
getSteps()
Step management.
setSubtypeClasses()
Register classes for core objects.
checkSettingsFile(&$report=array())
Check that the settings file exists.
checkPhpDirectives(&$phpReport)
Check PHP parameters.
checkPHP(&$report)
Check version of PHP, extensions, and variables.
validateSettingsVars($submissionVars, $formVars)
Validate the site settings form variables.
processRewriteTest()
Check if the request is coming from the URL rewrite test on the requirements page.
bootstrapConfig()
Set up configuration variables.
checkEngineDir(&$report)
Requirement checks support methods.
countNumConditions($report, $condition)
Count the number of failures in the requirements report.
batchInstall(array $params, $createHtaccess=FALSE)
A batch install of Elgg.
validateAdminVars($submissionVars, $formVars)
Admin account support methods.
__construct()
Constructor bootstraps the Elgg engine.
setInstallStatus()
Check the different install steps for completion.
resumeInstall($step)
Check if this is a case of a install being resumed and figure out where to continue from.
getNextStep($currentStep)
Get the next step as a string.
createSettingsFile($params)
Writes the settings file to the engine directory.
requirements($vars)
Requirements controller.
createAdminAccount($submissionVars, $login=FALSE)
Create a user account for the admin.
settings($submissionVars)
Site settings controller.
bootstrapEngine()
Bootstraping.
admin($submissionVars)
Admin account controller.
connectToDatabase()
Bootstrap database connection before entire engine is available.
database($submissionVars)
Database set up controller.
complete()
Controller for last step.
getNextStepUrl($currentStep)
Get the URL of the next step.
loadSettingsFile()
Load settings.php.
checkRewriteRules(&$report)
Confirm that the rewrite rules are firing.
enablePlugins()
Enable a set of default plugins.
installDatabase()
Create the database tables.
run($step)
Dispatches a request to one of the step controllers.
A Site entity.
Definition: ElggSite.php:28
datalist_get($name)
Get the value of a datalist element.
datalist_set($name, $value)
Set the value for a datalist element.
elgg_get_site_url($site_guid=0)
Get the URL for the current (or specified) site.
set_config($name, $value, $site_guid=0)
Add or update a config setting.
get_config($name, $site_guid=0)
Gets a configuration value.
$guid
Removes an admin notice.
register_error($error)
Display an error on next page load.
Definition: elgglib.php:605
elgg_trigger_event($event, $object_type, $object=null)
Trigger an Elgg Event and attempt to run all handler callbacks registered to that event,...
Definition: elgglib.php:720
sanitise_filepath($path, $append_slash=true)
Sanitise file paths ensuring that they begin and end with slashes etc.
Definition: elgglib.php:484
system_message($message)
Display a system message on next page load.
Definition: elgglib.php:592
elgg_get_version($human_readable=false)
Get the current Elgg version information.
Definition: elgglib.php:1126
elgg_unregister_event_handler($event, $object_type, $callback)
Unregisters a callback for an event.
Definition: elgglib.php:683
const ACCESS_PUBLIC
Definition: elgglib.php:2123
forward($location="", $reason='system')
Forward to $location.
Definition: elgglib.php:79
elgg_set_ignore_access($ignore=true)
Set if Elgg's access system should be ignored.
Definition: access.php:43
get_data($query, $callback="")
Retrieve rows from the database.
Definition: database.php:50
run_sql_script($scriptlocation)
Runs a full database script from disk.
Definition: database.php:130
get_current_language()
Detect the current language being used by the current site or logged in user.
Definition: languages.php:109
elgg_echo($message_key, $args=array(), $language="")
Given a message key, returns an appropriately translated full-text string.
Definition: languages.php:21
register_translations($path, $load_all=false)
When given a full path, finds translation files and loads them.
Definition: languages.php:255
create_metadata($entity_guid, $name, $value, $value_type='', $owner_guid=0, $access_id=ACCESS_PRIVATE, $allow_multiple=false)
Create a new metadata object, or update an existing one.
Definition: metadata.php:69
elgg_get_plugins($status='active', $site_guid=null)
Returns an ordered list of plugins.
Definition: plugins.php:372
_elgg_generate_plugin_entities()
Discovers plugins in the plugins_path setting and creates ElggPlugin entities for them if they don't ...
Definition: plugins.php:93
elgg_get_upgrade_files($upgrade_path=null)
Returns a list of upgrade files relative to the $upgrade_path dir.
Definition: upgrade.php:53
$lib_dir
Definition: start.php:61
$lib_files
Definition: start.php:69
get_entity($guid)
Loads and returns an entity object from a guid.
Definition: entities.php:604
add_subtype($type, $subtype, $class="")
Register ElggEntities with a certain type and subtype to be loaded as a specific class.
Definition: entities.php:331
$url
Definition: exceptions.php:24
$extensions
$lang
Definition: html.php:12
$value
Definition: longtext.php:29
is_email_address($address)
Validates an email address.
Definition: input.php:129
$step
Definition: install.php:19
$path
Definition: invalid.php:17
exit
Definition: reorder.php:12
$report
$key
Definition: summary.php:34
$extension
Definition: default.php:23
_elgg_session_boot()
Initializes the session and checks for the remember me cookie.
Definition: sessions.php:393
login(ElggUser $user, $persistent=false)
Logs in a specified ElggUser.
Definition: sessions.php:305
$plugin
global $CONFIG
if(file_exists($welcome)) $vars
Definition: upgrade.php:93
$upgrades
Lists pending upgrades.
Definition: upgrades.php:6
register_user($username, $password, $name, $email, $allow_multiple_emails=false)
Registers a user, returning false if the username already exists.
Definition: users.php:653
$version
Definition: version.php:14
$table
Definition: cron.php:28
$count
Definition: tools.php:19
$e
Definition: metadata.php:12
$defaults
Definition: access.php:19
elgg_view_page($title, $body, $page_shell='default', $vars=array())
Assembles and outputs a full page.
Definition: views.php:437
elgg_view($view, $vars=array(), $bypass=false, $ignored=false, $viewtype='')
Return a parsed view.
Definition: views.php:354
elgg_set_viewtype($viewtype="")
Manually set the viewtype.
Definition: views.php:70