Elgg  Version 1.10
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 
57  private $CONFIG;
58 
62  public function __construct() {
63  global $CONFIG;
64  if (!isset($CONFIG)) {
65  $CONFIG = new stdClass;
66  }
67 
68  $this->CONFIG = $CONFIG;
69 
70  $this->isAction = isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST';
71 
72  $this->bootstrapConfig();
73 
74  $this->bootstrapEngine();
75 
76  _elgg_services()->setValue('session', new ElggSession(new Elgg\Http\MockSessionStorage()));
77 
78  elgg_set_viewtype('installation');
79 
80  set_error_handler('_elgg_php_error_handler');
81  set_exception_handler('_elgg_php_exception_handler');
82 
83  _elgg_services()->translator->registerTranslations("{$this->getElggRoot()}/install/languages/", TRUE);
84  }
85 
89  private function getElggRoot() {
90  return dirname(dirname(__DIR__));
91  }
92 
101  public function run($step) {
102  global $CONFIG;
103 
104  // language needs to be set before the first call to elgg_echo()
105  $CONFIG->language = 'en';
106 
107  // check if this is a URL rewrite test coming in
108  $this->processRewriteTest();
109 
110  if (!in_array($step, $this->getSteps())) {
111  $msg = _elgg_services()->translator->translate('InstallationException:UnknownStep', array($step));
112  throw new InstallationException($msg);
113  }
114 
115  $this->setInstallStatus();
116 
118 
119  // check if this is an install being resumed
120  $this->resumeInstall($step);
121 
122  $this->finishBootstraping($step);
123 
124  $params = $this->getPostVariables();
125  $this->$step($params);
126  }
127 
135  public function setAutoLogin($flag) {
136  $this->autoLogin = (bool) $flag;
137  }
138 
157  public function batchInstall(array $params, $createHtaccess = FALSE) {
158 
159 
160  restore_error_handler();
161  restore_exception_handler();
162 
163  $defaults = array(
164  'dbhost' => 'localhost',
165  'dbprefix' => 'elgg_',
166  'language' => 'en',
167  'siteaccess' => ACCESS_PUBLIC,
168  );
169  $params = array_merge($defaults, $params);
170 
171  $requiredParams = array(
172  'dbuser',
173  'dbpassword',
174  'dbname',
175  'sitename',
176  'wwwroot',
177  'dataroot',
178  'displayname',
179  'email',
180  'username',
181  'password',
182  );
183  foreach ($requiredParams as $key) {
184  if (empty($params[$key])) {
185  $msg = _elgg_services()->translator->translate('install:error:requiredfield', array($key));
186  throw new InstallationException($msg);
187  }
188  }
189 
190  // password is passed in once
191  $params['password1'] = $params['password2'] = $params['password'];
192 
193  if ($createHtaccess) {
194  $rewriteTester = new ElggRewriteTester();
195  if (!$rewriteTester->createHtaccess($params['wwwroot'], $this->CONFIG->path)) {
196  throw new InstallationException(_elgg_services()->translator->translate('install:error:htaccess'));
197  }
198  }
199 
200  $this->setInstallStatus();
201 
202  if (!$this->status['config']) {
203  if (!$this->createSettingsFile($params)) {
204  throw new InstallationException(_elgg_services()->translator->translate('install:error:settings'));
205  }
206  }
207 
208  if (!$this->connectToDatabase()) {
209  throw new InstallationException(_elgg_services()->translator->translate('install:error:databasesettings'));
210  }
211 
212  if (!$this->status['database']) {
213  if (!$this->installDatabase()) {
214  throw new InstallationException(_elgg_services()->translator->translate('install:error:cannotloadtables'));
215  }
216  }
217 
218  // load remaining core libraries
219  $this->finishBootstraping('settings');
220 
221  if (!$this->saveSiteSettings($params)) {
222  throw new InstallationException(_elgg_services()->translator->translate('install:error:savesitesettings'));
223  }
224 
225  if (!$this->createAdminAccount($params)) {
226  throw new InstallationException(_elgg_services()->translator->translate('install:admin:cannot_create'));
227  }
228  }
229 
238  protected function render($step, $vars = array()) {
239 
240  $vars['next_step'] = $this->getNextStep($step);
241 
242  $title = _elgg_services()->translator->translate("install:$step");
243  $body = elgg_view("install/pages/$step", $vars);
244  echo elgg_view_page(
245  $title,
246  $body,
247  'default',
248  array(
249  'step' => $step,
250  'steps' => $this->getSteps(),
251  )
252  );
253  exit;
254  }
255 
267  protected function welcome($vars) {
268  $this->render('welcome');
269  }
270 
280  protected function requirements($vars) {
281 
282  $report = array();
283 
284  // check PHP parameters and libraries
285  $this->checkPHP($report);
286 
287  // check URL rewriting
288  $this->checkRewriteRules($report);
289 
290  // check for existence of settings file
291  if ($this->checkSettingsFile($report) != TRUE) {
292  // no file, so check permissions on engine directory
293  $this->checkEngineDir($report);
294  }
295 
296  // check the database later
297  $report['database'] = array(array(
298  'severity' => 'info',
299  'message' => _elgg_services()->translator->translate('install:check:database')
300  ));
301 
302  // any failures?
303  $numFailures = $this->countNumConditions($report, 'failure');
304 
305  // any warnings
306  $numWarnings = $this->countNumConditions($report, 'warning');
307 
308 
309  $params = array(
310  'report' => $report,
311  'num_failures' => $numFailures,
312  'num_warnings' => $numWarnings,
313  );
314 
315  $this->render('requirements', $params);
316  }
317 
327  protected function database($submissionVars) {
328 
329  $formVars = array(
330  'dbuser' => array(
331  'type' => 'text',
332  'value' => '',
333  'required' => TRUE,
334  ),
335  'dbpassword' => array(
336  'type' => 'password',
337  'value' => '',
338  'required' => FALSE,
339  ),
340  'dbname' => array(
341  'type' => 'text',
342  'value' => '',
343  'required' => TRUE,
344  ),
345  'dbhost' => array(
346  'type' => 'text',
347  'value' => 'localhost',
348  'required' => TRUE,
349  ),
350  'dbprefix' => array(
351  'type' => 'text',
352  'value' => 'elgg_',
353  'required' => TRUE,
354  ),
355  );
356 
357  if ($this->checkSettingsFile()) {
358  // user manually created settings file so we fake out action test
359  $this->isAction = TRUE;
360  }
361 
362  if ($this->isAction) {
363  do {
364  // only create settings file if it doesn't exist
365  if (!$this->checkSettingsFile()) {
366  if (!$this->validateDatabaseVars($submissionVars, $formVars)) {
367  // error so we break out of action and serve same page
368  break;
369  }
370 
371  if (!$this->createSettingsFile($submissionVars)) {
372  break;
373  }
374  }
375 
376  // check db version and connect
377  if (!$this->connectToDatabase()) {
378  break;
379  }
380 
381  if (!$this->installDatabase()) {
382  break;
383  }
384 
385  system_message(_elgg_services()->translator->translate('install:success:database'));
386 
387  $this->continueToNextStep('database');
388  } while (FALSE); // PHP doesn't support breaking out of if statements
389  }
390 
391  $formVars = $this->makeFormSticky($formVars, $submissionVars);
392 
393  $params = array('variables' => $formVars,);
394 
395  if ($this->checkSettingsFile()) {
396  // settings file exists and we're here so failed to create database
397  $params['failure'] = TRUE;
398  }
399 
400  $this->render('database', $params);
401  }
402 
412  protected function settings($submissionVars) {
413 
414 
415  $formVars = array(
416  'sitename' => array(
417  'type' => 'text',
418  'value' => 'My New Community',
419  'required' => TRUE,
420  ),
421  'siteemail' => array(
422  'type' => 'email',
423  'value' => '',
424  'required' => FALSE,
425  ),
426  'wwwroot' => array(
427  'type' => 'url',
428  'value' => _elgg_services()->config->getSiteUrl(),
429  'required' => TRUE,
430  ),
431  'dataroot' => array(
432  'type' => 'text',
433  'value' => '',
434  'required' => TRUE,
435  ),
436  'siteaccess' => array(
437  'type' => 'access',
438  'value' => ACCESS_PUBLIC,
439  'required' => TRUE,
440  ),
441  );
442 
443  // if Apache, we give user option of having Elgg create data directory
444  //if (ElggRewriteTester::guessWebServer() == 'apache') {
445  // $formVars['dataroot']['type'] = 'combo';
446  // $this->CONFIG->translations['en']['install:settings:help:dataroot'] =
447  // $this->CONFIG->translations['en']['install:settings:help:dataroot:apache'];
448  //}
449 
450  if ($this->isAction) {
451  do {
452  //if (!$this->createDataDirectory($submissionVars, $formVars)) {
453  // break;
454  //}
455 
456  if (!$this->validateSettingsVars($submissionVars, $formVars)) {
457  break;
458  }
459 
460  if (!$this->saveSiteSettings($submissionVars)) {
461  break;
462  }
463 
464  system_message(_elgg_services()->translator->translate('install:success:settings'));
465 
466  $this->continueToNextStep('settings');
467 
468  } while (FALSE); // PHP doesn't support breaking out of if statements
469  }
470 
471  $formVars = $this->makeFormSticky($formVars, $submissionVars);
472 
473  $this->render('settings', array('variables' => $formVars));
474  }
475 
485  protected function admin($submissionVars) {
486  $formVars = array(
487  'displayname' => array(
488  'type' => 'text',
489  'value' => '',
490  'required' => TRUE,
491  ),
492  'email' => array(
493  'type' => 'email',
494  'value' => '',
495  'required' => TRUE,
496  ),
497  'username' => array(
498  'type' => 'text',
499  'value' => '',
500  'required' => TRUE,
501  ),
502  'password1' => array(
503  'type' => 'password',
504  'value' => '',
505  'required' => TRUE,
506  'pattern' => '.{6,}',
507  ),
508  'password2' => array(
509  'type' => 'password',
510  'value' => '',
511  'required' => TRUE,
512  ),
513  );
514 
515  if ($this->isAction) {
516  do {
517  if (!$this->validateAdminVars($submissionVars, $formVars)) {
518  break;
519  }
520 
521  if (!$this->createAdminAccount($submissionVars, $this->autoLogin)) {
522  break;
523  }
524 
525  system_message(_elgg_services()->translator->translate('install:success:admin'));
526 
527  $this->continueToNextStep('admin');
528 
529  } while (FALSE); // PHP doesn't support breaking out of if statements
530  }
531 
532  // bit of a hack to get the password help to show right number of characters
533 
534  $lang = _elgg_services()->translator->getCurrentLanguage();
535  $this->CONFIG->translations[$lang]['install:admin:help:password1'] =
536  sprintf($this->CONFIG->translations[$lang]['install:admin:help:password1'],
537  $this->CONFIG->min_password_length);
538 
539  $formVars = $this->makeFormSticky($formVars, $submissionVars);
540 
541  $this->render('admin', array('variables' => $formVars));
542  }
543 
549  protected function complete() {
550 
551  $params = array();
552  if ($this->autoLogin) {
553  $params['destination'] = 'admin';
554  } else {
555  $params['destination'] = 'index.php';
556  }
557 
558  $this->render('complete', $params);
559  }
560 
570  protected function getSteps() {
571  return $this->steps;
572  }
573 
581  protected function continueToNextStep($currentStep) {
582  $this->isAction = FALSE;
583  forward($this->getNextStepUrl($currentStep));
584  }
585 
593  protected function getNextStep($currentStep) {
594  $index = 1 + array_search($currentStep, $this->steps);
595  if (isset($this->steps[$index])) {
596  return $this->steps[$index];
597  } else {
598  return null;
599  }
600  }
601 
609  protected function getNextStepUrl($currentStep) {
610  $nextStep = $this->getNextStep($currentStep);
611  return _elgg_services()->config->getSiteUrl() . "install.php?step=$nextStep";
612  }
613 
620  protected function setInstallStatus() {
621 
622 
623  if (!is_readable("{$this->CONFIG->path}engine/settings.php")) {
624  return;
625  }
626 
627  $this->loadSettingsFile();
628 
629  $this->status['config'] = TRUE;
630 
631  // must be able to connect to database to jump install steps
632  $dbSettingsPass = $this->checkDatabaseSettings(
633  $this->CONFIG->dbuser,
634  $this->CONFIG->dbpass,
635  $this->CONFIG->dbname,
636  $this->CONFIG->dbhost
637  );
638  if ($dbSettingsPass == FALSE) {
639  return;
640  }
641 
642  if (!include_once("{$this->CONFIG->path}engine/lib/database.php")) {
643  throw new InstallationException(_elgg_services()->translator->translate('InstallationException:MissingLibrary', array('database.php')));
644  }
645 
646  // check that the config table has been created
647  $query = "show tables";
648  $result = _elgg_services()->db->getData($query);
649  if ($result) {
650  foreach ($result as $table) {
651  $table = (array) $table;
652  if (in_array("{$this->CONFIG->dbprefix}config", $table)) {
653  $this->status['database'] = TRUE;
654  }
655  }
656  if ($this->status['database'] == FALSE) {
657  return;
658  }
659  } else {
660  // no tables
661  return;
662  }
663 
664  // check that the config table has entries
665  $query = "SELECT COUNT(*) AS total FROM {$this->CONFIG->dbprefix}config";
666  $result = _elgg_services()->db->getData($query);
667  if ($result && $result[0]->total > 0) {
668  $this->status['settings'] = TRUE;
669  } else {
670  return;
671  }
672 
673  // check that the users entity table has an entry
674  $query = "SELECT COUNT(*) AS total FROM {$this->CONFIG->dbprefix}users_entity";
675  $result = _elgg_services()->db->getData($query);
676  if ($result && $result[0]->total > 0) {
677  $this->status['admin'] = TRUE;
678  } else {
679  return;
680  }
681  }
682 
691  protected function checkInstallCompletion($step) {
692  if ($step != 'complete') {
693  if (!in_array(FALSE, $this->status)) {
694  // install complete but someone is trying to view an install page
695  forward();
696  }
697  }
698  }
699 
708  protected function resumeInstall($step) {
709  // only do a resume from the first step
710  if ($step !== 'welcome') {
711  return;
712  }
713 
714  if ($this->status['database'] == FALSE) {
715  return;
716  }
717 
718  if ($this->status['settings'] == FALSE) {
719  forward("install.php?step=settings");
720  }
721 
722  if ($this->status['admin'] == FALSE) {
723  forward("install.php?step=admin");
724  }
725 
726  // everything appears to be set up
727  forward("install.php?step=complete");
728  }
729 
739  protected function bootstrapEngine() {
740 
741 
742  require_once $this->CONFIG->path . 'engine/load.php';
743  }
744 
754  protected function finishBootstraping($step) {
755 
756  $dbIndex = array_search('database', $this->getSteps());
757  $settingsIndex = array_search('settings', $this->getSteps());
758  $adminIndex = array_search('admin', $this->getSteps());
759  $completeIndex = array_search('complete', $this->getSteps());
760  $stepIndex = array_search($step, $this->getSteps());
761 
762  // To log in the user, we need to use the Elgg core session handling.
763  // Otherwise, use default php session handling
764  $useElggSession = ($stepIndex == $adminIndex && $this->isAction) ||
765  $stepIndex == $completeIndex;
766  if (!$useElggSession) {
767  session_name('Elgg_install');
768  session_start();
769  _elgg_services()->events->unregisterHandler('boot', 'system', 'session_init');
770  }
771 
772  if ($stepIndex > $dbIndex) {
773  // once the database has been created, load rest of engine
774 
775  $lib_dir = $this->CONFIG->path . 'engine/lib/';
776 
777  $this->loadSettingsFile();
778 
779  $lib_files = array(
780  // these want to be loaded first apparently?
781  'autoloader.php',
782  'database.php',
783  'actions.php',
784 
785  'admin.php',
786  'annotations.php',
787  'cron.php',
788  'entities.php',
789  'extender.php',
790  'filestore.php',
791  'group.php',
792  'mb_wrapper.php',
793  'memcache.php',
794  'metadata.php',
795  'metastrings.php',
796  'navigation.php',
797  'notification.php',
798  'objects.php',
799  'pagehandler.php',
800  'pam.php',
801  'plugins.php',
802  'private_settings.php',
803  'relationships.php',
804  'river.php',
805  'sites.php',
806  'statistics.php',
807  'tags.php',
808  'user_settings.php',
809  'users.php',
810  'upgrade.php',
811  'widgets.php',
812  'deprecated-1.7.php',
813  'deprecated-1.8.php',
814  'deprecated-1.9.php',
815  );
816 
817  foreach ($lib_files as $file) {
818  $path = $lib_dir . $file;
819  if (!include_once($path)) {
820  throw new InstallationException('InstallationException:MissingLibrary', array($file));
821  }
822  }
823 
824  _elgg_services()->db->setupConnections();
825  _elgg_services()->translator->registerTranslations("{$this->getElggRoot()}/languages/");
826  $this->CONFIG->language = 'en';
827 
828  if ($stepIndex > $settingsIndex) {
829  $this->CONFIG->site_guid = (int) _elgg_services()->datalist->get('default_site');
830  $this->CONFIG->site_id = $this->CONFIG->site_guid;
831  $this->CONFIG->site = get_entity($this->CONFIG->site_guid);
832  $this->CONFIG->dataroot = _elgg_services()->datalist->get('dataroot');
834  }
835 
836  _elgg_services()->events->trigger('init', 'system');
837  }
838  }
839 
845  protected function bootstrapConfig() {
846  $this->CONFIG->installer_running = true;
847 
848  $this->CONFIG->wwwroot = $this->getBaseUrl();
849  $this->CONFIG->url = $this->CONFIG->wwwroot;
850  $this->CONFIG->path = "{$this->getElggRoot()}/";
851  $this->CONFIG->viewpath = $this->CONFIG->path . 'views/';
852  $this->CONFIG->pluginspath = $this->CONFIG->path . 'mod/';
853  $this->CONFIG->context = array();
854  $this->CONFIG->entity_types = array('group', 'object', 'site', 'user');
855  // required by elgg_view_page()
856  $this->CONFIG->sitename = '';
857  $this->CONFIG->sitedescription = '';
858  }
859 
863  private function isHttps() {
864  return (!empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") ||
865  $_SERVER['SERVER_PORT'] == 443;
866  }
867 
876  protected function getBaseUrl() {
877  $protocol = $this->isHttps() ? 'https' : 'http';
878 
879  if (isset($_SERVER["SERVER_PORT"])) {
880  $port = ':' . $_SERVER["SERVER_PORT"];
881  } else {
882  $port = '';
883  }
884  if ($port == ':80' || $port == ':443') {
885  $port = '';
886  }
887  $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
888  $cutoff = strpos($uri, 'install.php');
889  $uri = substr($uri, 0, $cutoff);
890  $serverName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
891 
892  return "$protocol://{$serverName}$port{$uri}";
893  }
894 
901  protected function loadSettingsFile() {
902 
903 
904  if (!include_once("{$this->CONFIG->path}engine/settings.php")) {
905  throw new InstallationException(_elgg_services()->translator->translate('InstallationException:CannotLoadSettings'));
906  }
907  }
908 
922  protected function getPostVariables() {
923  $vars = array();
924  foreach ($_POST as $k => $v) {
925  $vars[$k] = $v;
926  }
927  return $vars;
928  }
929 
938  protected function makeFormSticky($formVars, $submissionVars) {
939  foreach ($submissionVars as $field => $value) {
940  $formVars[$field]['value'] = $value;
941  }
942  return $formVars;
943  }
944 
956  protected function checkEngineDir(&$report) {
957 
958 
959  $writable = is_writable("{$this->CONFIG->path}engine");
960  if (!$writable) {
961  $report['settings'] = array(
962  array(
963  'severity' => 'failure',
964  'message' => _elgg_services()->translator->translate('install:check:enginedir'),
965  )
966  );
967  return FALSE;
968  }
969 
970  return TRUE;
971  }
972 
980  protected function checkSettingsFile(&$report = array()) {
981 
982 
983  if (!file_exists("{$this->CONFIG->path}engine/settings.php")) {
984  return FALSE;
985  }
986 
987  if (!is_readable("{$this->CONFIG->path}engine/settings.php")) {
988  $report['settings'] = array(
989  array(
990  'severity' => 'failure',
991  'message' => _elgg_services()->translator->translate('install:check:readsettings'),
992  )
993  );
994  }
995 
996  return TRUE;
997  }
998 
1006  protected function checkPHP(&$report) {
1007  $phpReport = array();
1008 
1009  $min_php_version = '5.4.0';
1010  if (version_compare(PHP_VERSION, $min_php_version, '<')) {
1011  $phpReport[] = array(
1012  'severity' => 'failure',
1013  'message' => _elgg_services()->translator->translate('install:check:php:version', array($min_php_version, PHP_VERSION))
1014  );
1015  }
1016 
1017  $this->checkPhpExtensions($phpReport);
1018 
1019  $this->checkPhpDirectives($phpReport);
1020 
1021  if (count($phpReport) == 0) {
1022  $phpReport[] = array(
1023  'severity' => 'pass',
1024  'message' => _elgg_services()->translator->translate('install:check:php:success')
1025  );
1026  }
1027 
1028  $report['php'] = $phpReport;
1029  }
1030 
1038  protected function checkPhpExtensions(&$phpReport) {
1039  $extensions = get_loaded_extensions();
1040  $requiredExtensions = array(
1041  'mysql',
1042  'json',
1043  'xml',
1044  'gd',
1045  );
1046  foreach ($requiredExtensions as $extension) {
1047  if (!in_array($extension, $extensions)) {
1048  $phpReport[] = array(
1049  'severity' => 'failure',
1050  'message' => _elgg_services()->translator->translate('install:check:php:extension', array($extension))
1051  );
1052  }
1053  }
1054 
1055  $recommendedExtensions = array(
1056  'mbstring',
1057  );
1058  foreach ($recommendedExtensions as $extension) {
1059  if (!in_array($extension, $extensions)) {
1060  $phpReport[] = array(
1061  'severity' => 'warning',
1062  'message' => _elgg_services()->translator->translate('install:check:php:extension:recommend', array($extension))
1063  );
1064  }
1065  }
1066  }
1067 
1075  protected function checkPhpDirectives(&$phpReport) {
1076  if (ini_get('open_basedir')) {
1077  $phpReport[] = array(
1078  'severity' => 'warning',
1079  'message' => _elgg_services()->translator->translate("install:check:php:open_basedir")
1080  );
1081  }
1082 
1083  if (ini_get('safe_mode')) {
1084  $phpReport[] = array(
1085  'severity' => 'warning',
1086  'message' => _elgg_services()->translator->translate("install:check:php:safe_mode")
1087  );
1088  }
1089 
1090  if (ini_get('arg_separator.output') !== '&') {
1091  $separator = htmlspecialchars(ini_get('arg_separator.output'));
1092  $msg = _elgg_services()->translator->translate("install:check:php:arg_separator", array($separator));
1093  $phpReport[] = array(
1094  'severity' => 'failure',
1095  'message' => $msg,
1096  );
1097  }
1098 
1099  if (ini_get('register_globals')) {
1100  $phpReport[] = array(
1101  'severity' => 'failure',
1102  'message' => _elgg_services()->translator->translate("install:check:php:register_globals")
1103  );
1104  }
1105 
1106  if (ini_get('session.auto_start')) {
1107  $phpReport[] = array(
1108  'severity' => 'failure',
1109  'message' => _elgg_services()->translator->translate("install:check:php:session.auto_start")
1110  );
1111  }
1112  }
1113 
1121  protected function checkRewriteRules(&$report) {
1122 
1123 
1124  $tester = new ElggRewriteTester();
1125  $url = _elgg_services()->config->getSiteUrl() . "rewrite.php";
1126  $report['rewrite'] = array($tester->run($url, $this->CONFIG->path));
1127  }
1128 
1135  protected function processRewriteTest() {
1136  if (strpos($_SERVER['REQUEST_URI'], 'rewrite.php') !== FALSE) {
1137  echo 'success';
1138  exit;
1139  }
1140  }
1141 
1150  protected function countNumConditions($report, $condition) {
1151  $count = 0;
1152  foreach ($report as $category => $checks) {
1153  foreach ($checks as $check) {
1154  if ($check['severity'] === $condition) {
1155  $count++;
1156  }
1157  }
1158  }
1159 
1160  return $count;
1161  }
1162 
1163 
1176  protected function validateDatabaseVars($submissionVars, $formVars) {
1177 
1178  foreach ($formVars as $field => $info) {
1179  if ($info['required'] == TRUE && !$submissionVars[$field]) {
1180  $name = _elgg_services()->translator->translate("install:database:label:$field");
1181  register_error(_elgg_services()->translator->translate('install:error:requiredfield', array($name)));
1182  return FALSE;
1183  }
1184  }
1185 
1186  // according to postgres documentation: SQL identifiers and key words must
1187  // begin with a letter (a-z, but also letters with diacritical marks and
1188  // non-Latin letters) or an underscore (_). Subsequent characters in an
1189  // identifier or key word can be letters, underscores, digits (0-9), or dollar signs ($).
1190  // Refs #4994
1191  if (!preg_match("/^[a-zA-Z_][\w]*$/", $submissionVars['dbprefix'])) {
1192  register_error(_elgg_services()->translator->translate('install:error:database_prefix'));
1193  return FALSE;
1194  }
1195 
1196  return $this->checkDatabaseSettings(
1197  $submissionVars['dbuser'],
1198  $submissionVars['dbpassword'],
1199  $submissionVars['dbname'],
1200  $submissionVars['dbhost']
1201  );
1202  }
1203 
1214  protected function checkDatabaseSettings($user, $password, $dbname, $host) {
1215  $mysql_dblink = mysql_connect($host, $user, $password, true);
1216  if ($mysql_dblink == FALSE) {
1217  register_error(_elgg_services()->translator->translate('install:error:databasesettings'));
1218  return FALSE;
1219  }
1220 
1221  $result = mysql_select_db($dbname, $mysql_dblink);
1222 
1223  // check MySQL version - must be 5.0 or >
1224  $required_version = 5.0;
1225  $version = mysql_get_server_info();
1226  $points = explode('.', $version);
1227  if ($points[0] < $required_version) {
1228  register_error(_elgg_services()->translator->translate('install:error:oldmysql', array($version)));
1229  return FALSE;
1230  }
1231 
1232  mysql_close($mysql_dblink);
1233 
1234  if (!$result) {
1235  register_error(_elgg_services()->translator->translate('install:error:nodatabase', array($dbname)));
1236  }
1237 
1238  return $result;
1239  }
1240 
1248  protected function createSettingsFile($params) {
1249 
1250 
1251  $templateFile = "{$this->CONFIG->path}engine/settings.example.php";
1252  $template = file_get_contents($templateFile);
1253  if (!$template) {
1254  register_error(_elgg_services()->translator->translate('install:error:readsettingsphp'));
1255  return FALSE;
1256  }
1257 
1258  foreach ($params as $k => $v) {
1259  $template = str_replace("{{" . $k . "}}", $v, $template);
1260  }
1261 
1262  $settingsFilename = "{$this->CONFIG->path}engine/settings.php";
1263  $result = file_put_contents($settingsFilename, $template);
1264  if (!$result) {
1265  register_error(_elgg_services()->translator->translate('install:error:writesettingphp'));
1266  return FALSE;
1267  }
1268 
1269  return TRUE;
1270  }
1271 
1277  protected function connectToDatabase() {
1278 
1279 
1280  if (!include_once("{$this->CONFIG->path}engine/settings.php")) {
1281  register_error('Elgg could not load the settings file. It does not exist or there is a file permissions issue.');
1282  return FALSE;
1283  }
1284 
1285  if (!include_once("{$this->CONFIG->path}engine/lib/database.php")) {
1286  register_error('Could not load database.php');
1287  return FALSE;
1288  }
1289 
1290  try {
1291  _elgg_services()->db->setupConnections();
1292  } catch (DatabaseException $e) {
1293  register_error($e->getMessage());
1294  return FALSE;
1295  }
1296 
1297  return TRUE;
1298  }
1299 
1305  protected function installDatabase() {
1306 
1307 
1308  try {
1309  _elgg_services()->db->runSqlScript("{$this->CONFIG->path}engine/schema/mysql.sql");
1310  } catch (Exception $e) {
1311  $msg = $e->getMessage();
1312  if (strpos($msg, 'already exists')) {
1313  $msg = _elgg_services()->translator->translate('install:error:tables_exist');
1314  }
1315  register_error($msg);
1316  return FALSE;
1317  }
1318 
1319  return TRUE;
1320  }
1321 
1334  protected function createDataDirectory(&$submissionVars, $formVars) {
1335  // did the user have option of Elgg creating the data directory
1336  if ($formVars['dataroot']['type'] != 'combo') {
1337  return TRUE;
1338  }
1339 
1340  // did the user select the option
1341  if ($submissionVars['dataroot'] != 'dataroot-checkbox') {
1342  return TRUE;
1343  }
1344 
1345  $dir = sanitise_filepath($submissionVars['path']) . 'data';
1346  if (file_exists($dir) || mkdir($dir, 0700)) {
1347  $submissionVars['dataroot'] = $dir;
1348  if (!file_exists("$dir/.htaccess")) {
1349  $htaccess = "Order Deny,Allow\nDeny from All\n";
1350  if (!file_put_contents("$dir/.htaccess", $htaccess)) {
1351  return FALSE;
1352  }
1353  }
1354  return TRUE;
1355  }
1356 
1357  return FALSE;
1358  }
1359 
1368  protected function validateSettingsVars($submissionVars, $formVars) {
1369 
1370 
1371  foreach ($formVars as $field => $info) {
1372  $submissionVars[$field] = trim($submissionVars[$field]);
1373  if ($info['required'] == TRUE && $submissionVars[$field] === '') {
1374  $name = _elgg_services()->translator->translate("install:settings:label:$field");
1375  register_error(_elgg_services()->translator->translate('install:error:requiredfield', array($name)));
1376  return FALSE;
1377  }
1378  }
1379 
1380  // check that data root is absolute path
1381  if (stripos(PHP_OS, 'win') === 0) {
1382  if (strpos($submissionVars['dataroot'], ':') !== 1) {
1383  $msg = _elgg_services()->translator->translate('install:error:relative_path', array($submissionVars['dataroot']));
1384  register_error($msg);
1385  return FALSE;
1386  }
1387  } else {
1388  if (strpos($submissionVars['dataroot'], '/') !== 0) {
1389  $msg = _elgg_services()->translator->translate('install:error:relative_path', array($submissionVars['dataroot']));
1390  register_error($msg);
1391  return FALSE;
1392  }
1393  }
1394 
1395  // check that data root exists
1396  if (!file_exists($submissionVars['dataroot'])) {
1397  $msg = _elgg_services()->translator->translate('install:error:datadirectoryexists', array($submissionVars['dataroot']));
1398  register_error($msg);
1399  return FALSE;
1400  }
1401 
1402  // check that data root is writable
1403  if (!is_writable($submissionVars['dataroot'])) {
1404  $msg = _elgg_services()->translator->translate('install:error:writedatadirectory', array($submissionVars['dataroot']));
1405  register_error($msg);
1406  return FALSE;
1407  }
1408 
1409  if (!isset($this->CONFIG->data_dir_override) || !$this->CONFIG->data_dir_override) {
1410  // check that data root is not subdirectory of Elgg root
1411  if (stripos($submissionVars['dataroot'], $submissionVars['path']) === 0) {
1412  $msg = _elgg_services()->translator->translate('install:error:locationdatadirectory', array($submissionVars['dataroot']));
1413  register_error($msg);
1414  return FALSE;
1415  }
1416  }
1417 
1418  // check that email address is email address
1419  if ($submissionVars['siteemail'] && !is_email_address($submissionVars['siteemail'])) {
1420  $msg = _elgg_services()->translator->translate('install:error:emailaddress', array($submissionVars['siteemail']));
1421  register_error($msg);
1422  return FALSE;
1423  }
1424 
1425  // @todo check that url is a url
1426  // @note filter_var cannot be used because it doesn't work on international urls
1427 
1428  return TRUE;
1429  }
1430 
1438  protected function saveSiteSettings($submissionVars) {
1439 
1440 
1441  // ensure that file path, data path, and www root end in /
1442  $submissionVars['path'] = sanitise_filepath($submissionVars['path']);
1443  $submissionVars['dataroot'] = sanitise_filepath($submissionVars['dataroot']);
1444  $submissionVars['wwwroot'] = sanitise_filepath($submissionVars['wwwroot']);
1445 
1446  $site = new ElggSite();
1447  $site->name = strip_tags($submissionVars['sitename']);
1448  $site->url = $submissionVars['wwwroot'];
1449  $site->access_id = ACCESS_PUBLIC;
1450  $site->email = $submissionVars['siteemail'];
1451  $guid = $site->save();
1452 
1453  if (!$guid) {
1454  register_error(_elgg_services()->translator->translate('install:error:createsite'));
1455  return FALSE;
1456  }
1457 
1458  // bootstrap site info
1459  $this->CONFIG->site_guid = $guid;
1460  $this->CONFIG->site_id = $guid;
1461  $this->CONFIG->site = $site;
1462 
1463  _elgg_services()->datalist->set('installed', time());
1464  _elgg_services()->datalist->set('path', $submissionVars['path']);
1465  _elgg_services()->datalist->set('dataroot', $submissionVars['dataroot']);
1466  _elgg_services()->datalist->set('default_site', $site->getGUID());
1467  _elgg_services()->datalist->set('version', elgg_get_version());
1468  _elgg_services()->datalist->set('simplecache_enabled', 1);
1469  _elgg_services()->datalist->set('system_cache_enabled', 1);
1470  _elgg_services()->datalist->set('simplecache_lastupdate', time());
1471 
1472  // new installations have run all the upgrades
1473  $upgrades = elgg_get_upgrade_files($submissionVars['path'] . 'engine/lib/upgrades/');
1474  _elgg_services()->datalist->set('processed_upgrades', serialize($upgrades));
1475 
1476  _elgg_services()->configTable->set('view', 'default', $site->getGUID());
1477  _elgg_services()->configTable->set('language', 'en', $site->getGUID());
1478  _elgg_services()->configTable->set('default_access', $submissionVars['siteaccess'], $site->getGUID());
1479  _elgg_services()->configTable->set('allow_registration', TRUE, $site->getGUID());
1480  _elgg_services()->configTable->set('walled_garden', FALSE, $site->getGUID());
1481  _elgg_services()->configTable->set('allow_user_default_access', '', $site->getGUID());
1482  _elgg_services()->configTable->set('default_limit', 10, $site->getGUID());
1483 
1484  $this->setSubtypeClasses();
1485 
1486  $this->enablePlugins();
1487 
1488  return TRUE;
1489  }
1490 
1496  protected function setSubtypeClasses() {
1497  add_subtype("object", "plugin", "ElggPlugin");
1498  add_subtype("object", "file", "ElggFile");
1499  add_subtype("object", "widget", "ElggWidget");
1500  add_subtype("object", "comment", "ElggComment");
1501  add_subtype("object", "elgg_upgrade", 'ElggUpgrade');
1502  }
1503 
1509  protected function enablePlugins() {
1511  $plugins = elgg_get_plugins('any');
1512  foreach ($plugins as $plugin) {
1513  if ($plugin->getManifest()) {
1514  if ($plugin->getManifest()->getActivateOnInstall()) {
1515  $plugin->activate();
1516  }
1517  if (in_array('theme', $plugin->getManifest()->getCategories())) {
1518  $plugin->setPriority('last');
1519  }
1520  }
1521  }
1522  }
1523 
1536  protected function validateAdminVars($submissionVars, $formVars) {
1537 
1538  foreach ($formVars as $field => $info) {
1539  if ($info['required'] == TRUE && !$submissionVars[$field]) {
1540  $name = _elgg_services()->translator->translate("install:admin:label:$field");
1541  register_error(_elgg_services()->translator->translate('install:error:requiredfield', array($name)));
1542  return FALSE;
1543  }
1544  }
1545 
1546  if ($submissionVars['password1'] !== $submissionVars['password2']) {
1547  register_error(_elgg_services()->translator->translate('install:admin:password:mismatch'));
1548  return FALSE;
1549  }
1550 
1551  if (trim($submissionVars['password1']) == "") {
1552  register_error(_elgg_services()->translator->translate('install:admin:password:empty'));
1553  return FALSE;
1554  }
1555 
1556  $minLength = _elgg_services()->configTable->get('min_password_length');
1557  if (strlen($submissionVars['password1']) < $minLength) {
1558  register_error(_elgg_services()->translator->translate('install:admin:password:tooshort'));
1559  return FALSE;
1560  }
1561 
1562  // check that email address is email address
1563  if ($submissionVars['email'] && !is_email_address($submissionVars['email'])) {
1564  $msg = _elgg_services()->translator->translate('install:error:emailaddress', array($submissionVars['email']));
1565  register_error($msg);
1566  return FALSE;
1567  }
1568 
1569  return TRUE;
1570  }
1571 
1580  protected function createAdminAccount($submissionVars, $login = FALSE) {
1581  try {
1582  $guid = register_user(
1583  $submissionVars['username'],
1584  $submissionVars['password1'],
1585  $submissionVars['displayname'],
1586  $submissionVars['email']
1587  );
1588  } catch (Exception $e) {
1589  register_error($e->getMessage());
1590  return false;
1591  }
1592 
1593  if (!$guid) {
1594  register_error(_elgg_services()->translator->translate('install:admin:cannot_create'));
1595  return false;
1596  }
1597 
1598  $user = get_entity($guid);
1599  if (!$user instanceof ElggUser) {
1600  register_error(_elgg_services()->translator->translate('install:error:loadadmin'));
1601  return false;
1602  }
1603 
1604  elgg_set_ignore_access(TRUE);
1605  if ($user->makeAdmin() == FALSE) {
1606  register_error(_elgg_services()->translator->translate('install:error:adminaccess'));
1607  } else {
1608  _elgg_services()->datalist->set('admin_registered', 1);
1609  }
1610  elgg_set_ignore_access(false);
1611 
1612  // add validation data to satisfy user validation plugins
1613  create_metadata($guid, 'validated', TRUE, '', 0, ACCESS_PUBLIC);
1614  create_metadata($guid, 'validated_method', 'admin_user', '', 0, ACCESS_PUBLIC);
1615 
1616  if ($login) {
1618  $storage = new Elgg\Http\NativeSessionStorage(array(), $handler);
1619  $session = new ElggSession($storage);
1620  $session->setName('Elgg');
1621  _elgg_services()->setValue('session', $session);
1622  if (login($user) == FALSE) {
1623  register_error(_elgg_services()->translator->translate('install:error:adminlogin'));
1624  }
1625  }
1626 
1627  return TRUE;
1628  }
1629 }
$password
Definition: login.php:25
$session
Definition: login.php:9
$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
if(! $autoload_available) _elgg_services()
Definition: autoloader.php:20
$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
$guid
Removes an admin notice.
register_error($error)
Display an error on next page load.
Definition: elgglib.php:489
sanitise_filepath($path, $append_slash=true)
Sanitise file paths ensuring that they begin and end with slashes etc.
Definition: elgglib.php:368
system_message($message)
Display a system message on next page load.
Definition: elgglib.php:476
elgg_get_version($human_readable=false)
Get the current Elgg version information.
Definition: elgglib.php:1010
const ACCESS_PUBLIC
Definition: elgglib.php:2048
forward($location="", $reason='system')
Forward to $location.
Definition: elgglib.php:80
elgg_set_ignore_access($ignore=true)
Set if Elgg's access system should be ignored.
Definition: access.php:43
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:65
elgg_get_plugins($status='active', $site_guid=null)
Returns an ordered list of plugins.
Definition: plugins.php:162
_elgg_generate_plugin_entities()
Discovers plugins in the plugins_path setting and creates \ElggPlugin entities for them if they don't...
Definition: plugins.php:75
elgg_get_upgrade_files($upgrade_path=null)
Returns a list of upgrade files relative to the $upgrade_path dir.
Definition: upgrade.php:53
get_entity($guid)
Loads and returns an entity object from a guid.
Definition: entities.php:382
add_subtype($type, $subtype, $class="")
Register \ElggEntities with a certain type and subtype to be loaded as a specific class.
Definition: entities.php:248
$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:88
$step
Definition: install.php:19
$path
Definition: invalid.php:17
$lib_dir
This file is used to make all of Elgg's code available without going through the boot process.
Definition: load.php:10
$lib_files
Definition: load.php:15
Save menu items.
if(! $limit=(int) elgg_extract('limit', $vars, elgg_get_config('default_limit'))) $count
Definition: pagination.php:26
exit
Definition: reorder.php:12
$report
$key
Definition: summary.php:34
$extension
Definition: default.php:23
login(\ElggUser $user, $persistent=false)
Logs in a specified \ElggUser.
Definition: sessions.php:320
_elgg_session_boot()
Initializes the session and checks for the remember me cookie.
Definition: sessions.php:408
$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:316
$version
Definition: version.php:14
$table
Definition: cron.php:28
$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