Elgg  Version 2.3
ElggInstaller.php
Go to the documentation of this file.
1 <?php
2 
4 
33 
34  protected $steps = array(
35  'welcome',
36  'requirements',
37  'database',
38  'settings',
39  'admin',
40  'complete',
41  );
42 
43  protected $status = array(
44  'config' => FALSE,
45  'database' => FALSE,
46  'settings' => FALSE,
47  'admin' => FALSE,
48  );
49 
50  protected $isAction = FALSE;
51 
52  protected $autoLogin = TRUE;
53 
54  private $view_path = '';
55 
61  private $CONFIG;
62 
66  public function __construct() {
67  global $CONFIG;
68  if (!isset($CONFIG)) {
69  $CONFIG = new stdClass;
70  }
71 
72  global $_ELGG;
73  if (!isset($_ELGG)) {
74  $_ELGG = new stdClass;
75  }
76 
77  $this->CONFIG = $CONFIG;
78 
79  $this->isAction = isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST';
80 
81  $this->bootstrapConfig();
82 
83  $this->bootstrapEngine();
84 
85  _elgg_services()->views->view_path = $this->view_path;
86 
87  _elgg_services()->setValue('session', \ElggSession::getMock());
88 
89  elgg_set_viewtype('installation');
90 
91  set_error_handler('_elgg_php_error_handler');
92  set_exception_handler('_elgg_php_exception_handler');
93 
94  _elgg_services()->config->set('simplecache_enabled', false);
95  _elgg_services()->translator->registerTranslations(\Elgg\Application::elggDir()->getPath("/install/languages/"), TRUE);
96  _elgg_services()->views->registerPluginViews(\Elgg\Application::elggDir()->getPath("/"));
97  }
98 
107  public function run($step) {
108  global $CONFIG;
109 
110  // language needs to be set before the first call to elgg_echo()
111  $CONFIG->language = 'en';
112 
113  // check if this is a URL rewrite test coming in
114  $this->processRewriteTest();
115 
116  if (!in_array($step, $this->getSteps())) {
117  $msg = _elgg_services()->translator->translate('InstallationException:UnknownStep', array($step));
118  throw new InstallationException($msg);
119  }
120 
121  $this->setInstallStatus();
122 
123  $this->checkInstallCompletion($step);
124 
125  // check if this is an install being resumed
126  $this->resumeInstall($step);
127 
128  $this->finishBootstraping($step);
129 
130  $params = $this->getPostVariables();
131 
132  $this->$step($params);
133  }
134 
142  public function setAutoLogin($flag) {
143  $this->autoLogin = (bool) $flag;
144  }
145 
164  public function batchInstall(array $params, $createHtaccess = FALSE) {
165 
166 
167  restore_error_handler();
168  restore_exception_handler();
169 
170  $defaults = array(
171  'dbhost' => 'localhost',
172  'dbprefix' => 'elgg_',
173  'language' => 'en',
174  'siteaccess' => ACCESS_PUBLIC,
175  'site_guid' => 1,
176  );
177  $params = array_merge($defaults, $params);
178 
179  $requiredParams = array(
180  'dbuser',
181  'dbpassword',
182  'dbname',
183  'sitename',
184  'wwwroot',
185  'dataroot',
186  'displayname',
187  'email',
188  'username',
189  'password',
190  );
191  foreach ($requiredParams as $key) {
192  if (empty($params[$key])) {
193  $msg = _elgg_services()->translator->translate('install:error:requiredfield', array($key));
194  throw new InstallationException($msg);
195  }
196  }
197 
198  // password is passed in once
199  $params['password1'] = $params['password2'] = $params['password'];
200 
201  if ($createHtaccess) {
202  $rewriteTester = new ElggRewriteTester();
203  if (!$rewriteTester->createHtaccess($params['wwwroot'], Directory\Local::root()->getPath())) {
204  throw new InstallationException(_elgg_services()->translator->translate('install:error:htaccess'));
205  }
206  }
207 
208  $this->setInstallStatus();
209 
210  if (!$this->status['config']) {
211  if (!$this->createSettingsFile($params)) {
212  throw new InstallationException(_elgg_services()->translator->translate('install:error:settings'));
213  }
214  }
215 
216  if (!$this->connectToDatabase()) {
217  throw new InstallationException(_elgg_services()->translator->translate('install:error:databasesettings'));
218  }
219 
220  if (!$this->status['database']) {
221  if (!$this->installDatabase()) {
222  throw new InstallationException(_elgg_services()->translator->translate('install:error:cannotloadtables'));
223  }
224  }
225 
226  // load remaining core libraries
227  $this->finishBootstraping('settings');
228 
229  if (!$this->saveSiteSettings($params)) {
230  throw new InstallationException(_elgg_services()->translator->translate('install:error:savesitesettings'));
231  }
232 
233  if (!$this->createAdminAccount($params)) {
234  throw new InstallationException(_elgg_services()->translator->translate('install:admin:cannot_create'));
235  }
236  }
237 
246  protected function render($step, $vars = array()) {
247  $vars['next_step'] = $this->getNextStep($step);
248 
249  $title = _elgg_services()->translator->translate("install:$step");
250  $body = elgg_view("install/pages/$step", $vars);
251 
253  $title,
254  $body,
255  'default',
256  array(
257  'step' => $step,
258  'steps' => $this->getSteps(),
259  )
260  );
261  exit;
262  }
263 
275  protected function welcome($vars) {
276  $this->render('welcome');
277  }
278 
288  protected function requirements($vars) {
289 
290  $report = array();
291 
292  // check PHP parameters and libraries
293  $this->checkPHP($report);
294 
295  // check URL rewriting
296  $this->checkRewriteRules($report);
297 
298  // check for existence of settings file
299  if ($this->checkSettingsFile($report) != TRUE) {
300  // no file, so check permissions on engine directory
302  }
303 
304  // check the database later
305  $report['database'] = array(array(
306  'severity' => 'info',
307  'message' => _elgg_services()->translator->translate('install:check:database')
308  ));
309 
310  // any failures?
311  $numFailures = $this->countNumConditions($report, 'failure');
312 
313  // any warnings
314  $numWarnings = $this->countNumConditions($report, 'warning');
315 
316 
317  $params = array(
318  'report' => $report,
319  'num_failures' => $numFailures,
320  'num_warnings' => $numWarnings,
321  );
322 
323  $this->render('requirements', $params);
324  }
325 
335  protected function database($submissionVars) {
336 
337  $formVars = array(
338  'dbuser' => array(
339  'type' => 'text',
340  'value' => '',
341  'required' => TRUE,
342  ),
343  'dbpassword' => array(
344  'type' => 'password',
345  'value' => '',
346  'required' => FALSE,
347  ),
348  'dbname' => array(
349  'type' => 'text',
350  'value' => '',
351  'required' => TRUE,
352  ),
353  'dbhost' => array(
354  'type' => 'text',
355  'value' => 'localhost',
356  'required' => TRUE,
357  ),
358  'dbprefix' => array(
359  'type' => 'text',
360  'value' => 'elgg_',
361  'required' => TRUE,
362  ),
363  'timezone' => array(
364  'type' => 'dropdown',
365  'value' => 'UTC',
366  'options' => \DateTimeZone::listIdentifiers(),
367  'required' => TRUE
368  )
369  );
370 
371  if ($this->checkSettingsFile()) {
372  // user manually created settings file so we fake out action test
373  $this->isAction = TRUE;
374  }
375 
376  if ($this->isAction) {
377  do {
378  // only create settings file if it doesn't exist
379  if (!$this->checkSettingsFile()) {
380  if (!$this->validateDatabaseVars($submissionVars, $formVars)) {
381  // error so we break out of action and serve same page
382  break;
383  }
384 
385  if (!$this->createSettingsFile($submissionVars)) {
386  break;
387  }
388  }
389 
390  // check db version and connect
391  if (!$this->connectToDatabase()) {
392  break;
393  }
394 
395  if (!$this->installDatabase()) {
396  break;
397  }
398 
399  system_message(_elgg_services()->translator->translate('install:success:database'));
400 
401  $this->continueToNextStep('database');
402  } while (FALSE); // PHP doesn't support breaking out of if statements
403  }
404 
405  $formVars = $this->makeFormSticky($formVars, $submissionVars);
406 
407  $params = array('variables' => $formVars,);
408 
409  if ($this->checkSettingsFile()) {
410  // settings file exists and we're here so failed to create database
411  $params['failure'] = TRUE;
412  }
413 
414  $this->render('database', $params);
415  }
416 
426  protected function settings($submissionVars) {
427 
428 
429  $formVars = array(
430  'sitename' => array(
431  'type' => 'text',
432  'value' => 'My New Community',
433  'required' => TRUE,
434  ),
435  'siteemail' => array(
436  'type' => 'email',
437  'value' => '',
438  'required' => FALSE,
439  ),
440  'wwwroot' => array(
441  'type' => 'url',
442  'value' => _elgg_services()->config->getSiteUrl(),
443  'required' => TRUE,
444  ),
445  'dataroot' => array(
446  'type' => 'text',
447  'value' => '',
448  'required' => TRUE,
449  ),
450  'siteaccess' => array(
451  'type' => 'access',
452  'value' => ACCESS_PUBLIC,
453  'required' => TRUE,
454  ),
455  );
456 
457  // if Apache, we give user option of having Elgg create data directory
458  //if (ElggRewriteTester::guessWebServer() == 'apache') {
459  // $formVars['dataroot']['type'] = 'combo';
460  // $GLOBALS['_ELGG']->translations['en']['install:settings:help:dataroot'] =
461  // $GLOBALS['_ELGG']->translations['en']['install:settings:help:dataroot:apache'];
462  //}
463 
464  if ($this->isAction) {
465  do {
466  //if (!$this->createDataDirectory($submissionVars, $formVars)) {
467  // break;
468  //}
469 
470  if (!$this->validateSettingsVars($submissionVars, $formVars)) {
471  break;
472  }
473 
474  if (!$this->saveSiteSettings($submissionVars)) {
475  break;
476  }
477 
478  system_message(_elgg_services()->translator->translate('install:success:settings'));
479 
480  $this->continueToNextStep('settings');
481 
482  } while (FALSE); // PHP doesn't support breaking out of if statements
483  }
484 
485  $formVars = $this->makeFormSticky($formVars, $submissionVars);
486 
487  $this->render('settings', array('variables' => $formVars));
488  }
489 
499  protected function admin($submissionVars) {
500  $formVars = array(
501  'displayname' => array(
502  'type' => 'text',
503  'value' => '',
504  'required' => TRUE,
505  ),
506  'email' => array(
507  'type' => 'email',
508  'value' => '',
509  'required' => TRUE,
510  ),
511  'username' => array(
512  'type' => 'text',
513  'value' => '',
514  'required' => TRUE,
515  ),
516  'password1' => array(
517  'type' => 'password',
518  'value' => '',
519  'required' => TRUE,
520  'pattern' => '.{6,}',
521  ),
522  'password2' => array(
523  'type' => 'password',
524  'value' => '',
525  'required' => TRUE,
526  ),
527  );
528 
529  if ($this->isAction) {
530  do {
531  if (!$this->validateAdminVars($submissionVars, $formVars)) {
532  break;
533  }
534 
535  if (!$this->createAdminAccount($submissionVars, $this->autoLogin)) {
536  break;
537  }
538 
539  system_message(_elgg_services()->translator->translate('install:success:admin'));
540 
541  $this->continueToNextStep('admin');
542 
543  } while (FALSE); // PHP doesn't support breaking out of if statements
544  }
545 
546  // bit of a hack to get the password help to show right number of characters
547 
548  $lang = _elgg_services()->translator->getCurrentLanguage();
549  $GLOBALS['_ELGG']->translations[$lang]['install:admin:help:password1'] =
550  sprintf($GLOBALS['_ELGG']->translations[$lang]['install:admin:help:password1'],
551  $this->CONFIG->min_password_length);
552 
553  $formVars = $this->makeFormSticky($formVars, $submissionVars);
554 
555  $this->render('admin', array('variables' => $formVars));
556  }
557 
563  protected function complete() {
564 
565  $params = array();
566  if ($this->autoLogin) {
567  $params['destination'] = 'admin';
568  } else {
569  $params['destination'] = 'index.php';
570  }
571 
572  $this->render('complete', $params);
573  }
574 
584  protected function getSteps() {
585  return $this->steps;
586  }
587 
595  protected function continueToNextStep($currentStep) {
596  $this->isAction = FALSE;
597  forward($this->getNextStepUrl($currentStep));
598  }
599 
607  protected function getNextStep($currentStep) {
608  $index = 1 + array_search($currentStep, $this->steps);
609  if (isset($this->steps[$index])) {
610  return $this->steps[$index];
611  } else {
612  return null;
613  }
614  }
615 
623  protected function getNextStepUrl($currentStep) {
624  $nextStep = $this->getNextStep($currentStep);
625  return _elgg_services()->config->getSiteUrl() . "install.php?step=$nextStep";
626  }
627 
634  protected function setInstallStatus() {
635  $settings_found = false;
636  foreach (_elgg_services()->config->getSettingsPaths() as $path) {
637  if (is_file($path) && is_readable($path)) {
638  $settings_found = true;
639  break;
640  }
641  }
642 
643  if (!$settings_found) {
644  return;
645  }
646 
647  $this->loadSettingsFile();
648 
649  $this->status['config'] = TRUE;
650 
651  // must be able to connect to database to jump install steps
652  $dbSettingsPass = $this->checkDatabaseSettings(
653  $this->CONFIG->dbuser,
654  $this->CONFIG->dbpass,
655  $this->CONFIG->dbname,
656  $this->CONFIG->dbhost
657  );
658 
659  if ($dbSettingsPass == FALSE) {
660  return;
661  }
662 
663  if (!include_once(\Elgg\Application::elggDir()->getPath("engine/lib/database.php"))) {
664  throw new InstallationException(_elgg_services()->translator->translate('InstallationException:MissingLibrary', array('database.php')));
665  }
666 
667  // check that the config table has been created
668  $query = "show tables";
669  $result = _elgg_services()->db->getData($query);
670  if ($result) {
671  foreach ($result as $table) {
672  $table = (array) $table;
673  if (in_array("{$this->CONFIG->dbprefix}config", $table)) {
674  $this->status['database'] = TRUE;
675  }
676  }
677  if ($this->status['database'] == FALSE) {
678  return;
679  }
680  } else {
681  // no tables
682  return;
683  }
684 
685  // check that the config table has entries
686  $query = "SELECT COUNT(*) AS total FROM {$this->CONFIG->dbprefix}config";
687  $result = _elgg_services()->db->getData($query);
688  if ($result && $result[0]->total > 0) {
689  $this->status['settings'] = TRUE;
690  } else {
691  return;
692  }
693 
694  // check that the users entity table has an entry
695  $query = "SELECT COUNT(*) AS total FROM {$this->CONFIG->dbprefix}users_entity";
696  $result = _elgg_services()->db->getData($query);
697  if ($result && $result[0]->total > 0) {
698  $this->status['admin'] = TRUE;
699  } else {
700  return;
701  }
702  }
703 
712  protected function checkInstallCompletion($step) {
713  if ($step != 'complete') {
714  if (!in_array(FALSE, $this->status)) {
715  // install complete but someone is trying to view an install page
716  forward();
717  }
718  }
719  }
720 
729  protected function resumeInstall($step) {
730  // only do a resume from the first step
731  if ($step !== 'welcome') {
732  return;
733  }
734 
735  if ($this->status['database'] == FALSE) {
736  return;
737  }
738 
739  if ($this->status['settings'] == FALSE) {
740  forward("install.php?step=settings");
741  }
742 
743  if ($this->status['admin'] == FALSE) {
744  forward("install.php?step=admin");
745  }
746 
747  // everything appears to be set up
748  forward("install.php?step=complete");
749  }
750 
760  protected function bootstrapEngine() {
761  $config = new \Elgg\Config($this->CONFIG);
762  $services = new \Elgg\Di\ServiceProvider($config);
763  (new \Elgg\Application($services))->loadCore();
764  }
765 
775  protected function finishBootstraping($step) {
776 
777  $dbIndex = array_search('database', $this->getSteps());
778  $settingsIndex = array_search('settings', $this->getSteps());
779  $adminIndex = array_search('admin', $this->getSteps());
780  $completeIndex = array_search('complete', $this->getSteps());
781  $stepIndex = array_search($step, $this->getSteps());
782 
783  // To log in the user, we need to use the Elgg core session handling.
784  // Otherwise, use default php session handling
785  $useElggSession = ($stepIndex == $adminIndex && $this->isAction) ||
786  $stepIndex == $completeIndex;
787  if (!$useElggSession) {
788  session_name('Elgg_install');
789  session_start();
790  _elgg_services()->events->unregisterHandler('boot', 'system', 'session_init');
791  }
792 
793  if ($stepIndex > $dbIndex) {
794  // once the database has been created, load rest of engine
795 
796  $lib_dir = \Elgg\Application::elggDir()->chroot('/engine/lib/');
797 
798  $this->loadSettingsFile();
799 
800  $lib_files = array(
801  // these want to be loaded first apparently?
802  'autoloader.php',
803  'database.php',
804  'actions.php',
805 
806  'admin.php',
807  'annotations.php',
808  'cron.php',
809  'entities.php',
810  'extender.php',
811  'filestore.php',
812  'group.php',
813  'mb_wrapper.php',
814  'memcache.php',
815  'metadata.php',
816  'metastrings.php',
817  'navigation.php',
818  'notification.php',
819  'objects.php',
820  'pagehandler.php',
821  'pam.php',
822  'plugins.php',
823  'private_settings.php',
824  'relationships.php',
825  'river.php',
826  'sites.php',
827  'statistics.php',
828  'tags.php',
829  'user_settings.php',
830  'users.php',
831  'upgrade.php',
832  'widgets.php',
833  'deprecated-1.9.php',
834  );
835 
836  foreach ($lib_files as $file) {
837  if (!include_once($lib_dir->getPath($file))) {
838  throw new InstallationException('InstallationException:MissingLibrary', array($file));
839  }
840  }
841 
842  _elgg_services()->db->setupConnections();
843  _elgg_services()->translator->registerTranslations(\Elgg\Application::elggDir()->getPath("/languages/"));
844  $this->CONFIG->language = 'en';
845 
846  if ($stepIndex > $settingsIndex) {
847  $this->CONFIG->site_guid = (int) _elgg_services()->datalist->get('default_site');
848  $this->CONFIG->site_id = $this->CONFIG->site_guid;
849  $this->CONFIG->site = get_entity($this->CONFIG->site_guid);
850  $this->CONFIG->dataroot = _elgg_services()->datalist->get('dataroot');
851  _elgg_services()->config->getCookieConfig();
853  }
854 
855  _elgg_services()->events->trigger('init', 'system');
856  }
857  }
858 
864  protected function bootstrapConfig() {
865  $this->CONFIG->installer_running = true;
866 
867  $this->CONFIG->wwwroot = $this->getBaseUrl();
868  $this->CONFIG->url = $this->CONFIG->wwwroot;
869  $this->CONFIG->path = \Elgg\Application::elggDir()->getPath() . "/";
870  $this->view_path = $this->CONFIG->path . 'views/';
871  $this->CONFIG->pluginspath = $this->CONFIG->path . 'mod/';
872  $this->CONFIG->context = array();
873  $this->CONFIG->entity_types = array('group', 'object', 'site', 'user');
874 
875  // required by elgg_view_page()
876  $this->CONFIG->sitename = '';
877  $this->CONFIG->sitedescription = '';
878 
879  // required by Elgg\Config::get
880  $this->CONFIG->site_guid = 1;
881  }
882 
886  private function isHttps() {
887  return (!empty($_SERVER["HTTPS"]) && strtolower($_SERVER["HTTPS"]) !== "off") ||
888  (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443);
889  }
890 
899  protected function getBaseUrl() {
900  $protocol = $this->isHttps() ? 'https' : 'http';
901 
902  if (isset($_SERVER["SERVER_PORT"])) {
903  $port = ':' . $_SERVER["SERVER_PORT"];
904  } else {
905  $port = '';
906  }
907  if ($port == ':80' || $port == ':443') {
908  $port = '';
909  }
910  $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
911  $cutoff = strpos($uri, 'install.php');
912  $uri = substr($uri, 0, $cutoff);
913  $serverName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
914 
915  return "$protocol://{$serverName}$port{$uri}";
916  }
917 
924  protected function loadSettingsFile() {
925  try {
926  _elgg_services()->config->loadSettingsFile();
927  } catch (\Exception $e) {
928  $msg = _elgg_services()->translator->translate('InstallationException:CannotLoadSettings');
929  throw new InstallationException($msg, 0, $e);
930  }
931  }
932 
946  protected function getPostVariables() {
947  $vars = array();
948  foreach ($_POST as $k => $v) {
949  $vars[$k] = $v;
950  }
951  return $vars;
952  }
953 
962  protected function makeFormSticky($formVars, $submissionVars) {
963  foreach ($submissionVars as $field => $value) {
964  $formVars[$field]['value'] = $value;
965  }
966  return $formVars;
967  }
968 
980  protected function isInstallDirWritable(&$report) {
981  $root = Directory\Local::root()->getPath();
982  $abs_path = \Elgg\Application::elggDir()->getPath('elgg-config');
983 
984  if (0 === strpos($abs_path, $root)) {
985  $relative_path = substr($abs_path, strlen($root));
986  } else {
987  $relative_path = $abs_path;
988  }
989  $relative_path = rtrim($relative_path, '/\\');
990 
991  $writable = is_writable(Directory\Local::root()->getPath('elgg-config'));
992  if (!$writable) {
993  $report['settings'] = array(
994  array(
995  'severity' => 'failure',
996  'message' => _elgg_services()->translator->translate('install:check:installdir', [$relative_path]),
997  )
998  );
999  return FALSE;
1000  }
1001 
1002  return TRUE;
1003  }
1004 
1012  protected function checkSettingsFile(&$report = array()) {
1013  if (!is_file($this->getSettingsPath())) {
1014  return FALSE;
1015  }
1016 
1017  if (!is_readable($this->getSettingsPath())) {
1018  $report['settings'] = array(
1019  array(
1020  'severity' => 'failure',
1021  'message' => _elgg_services()->translator->translate('install:check:readsettings'),
1022  )
1023  );
1024  }
1025 
1026  return TRUE;
1027  }
1028 
1034  private function getSettingsPath() {
1035  return Directory\Local::root()->getPath("elgg-config/settings.php");
1036  }
1037 
1045  protected function checkPHP(&$report) {
1046  $phpReport = array();
1047 
1048  $min_php_version = '5.6.0';
1049  if (version_compare(PHP_VERSION, $min_php_version, '<')) {
1050  $phpReport[] = array(
1051  'severity' => 'failure',
1052  'message' => _elgg_services()->translator->translate('install:check:php:version', array($min_php_version, PHP_VERSION))
1053  );
1054  }
1055 
1056  $this->checkPhpExtensions($phpReport);
1057 
1058  $this->checkPhpDirectives($phpReport);
1059 
1060  if (count($phpReport) == 0) {
1061  $phpReport[] = array(
1062  'severity' => 'pass',
1063  'message' => _elgg_services()->translator->translate('install:check:php:success')
1064  );
1065  }
1066 
1067  $report['php'] = $phpReport;
1068  }
1069 
1077  protected function checkPhpExtensions(&$phpReport) {
1078  $extensions = get_loaded_extensions();
1079  $requiredExtensions = array(
1080  'pdo_mysql',
1081  'json',
1082  'xml',
1083  'gd',
1084  );
1085  foreach ($requiredExtensions as $extension) {
1086  if (!in_array($extension, $extensions)) {
1087  $phpReport[] = array(
1088  'severity' => 'failure',
1089  'message' => _elgg_services()->translator->translate('install:check:php:extension', array($extension))
1090  );
1091  }
1092  }
1093 
1094  $recommendedExtensions = array(
1095  'mbstring',
1096  );
1097  foreach ($recommendedExtensions as $extension) {
1098  if (!in_array($extension, $extensions)) {
1099  $phpReport[] = array(
1100  'severity' => 'warning',
1101  'message' => _elgg_services()->translator->translate('install:check:php:extension:recommend', array($extension))
1102  );
1103  }
1104  }
1105  }
1106 
1114  protected function checkPhpDirectives(&$phpReport) {
1115  if (ini_get('open_basedir')) {
1116  $phpReport[] = array(
1117  'severity' => 'warning',
1118  'message' => _elgg_services()->translator->translate("install:check:php:open_basedir")
1119  );
1120  }
1121 
1122  if (ini_get('safe_mode')) {
1123  $phpReport[] = array(
1124  'severity' => 'warning',
1125  'message' => _elgg_services()->translator->translate("install:check:php:safe_mode")
1126  );
1127  }
1128 
1129  if (ini_get('arg_separator.output') !== '&') {
1130  $separator = htmlspecialchars(ini_get('arg_separator.output'));
1131  $msg = _elgg_services()->translator->translate("install:check:php:arg_separator", array($separator));
1132  $phpReport[] = array(
1133  'severity' => 'failure',
1134  'message' => $msg,
1135  );
1136  }
1137 
1138  if (ini_get('register_globals')) {
1139  $phpReport[] = array(
1140  'severity' => 'failure',
1141  'message' => _elgg_services()->translator->translate("install:check:php:register_globals")
1142  );
1143  }
1144 
1145  if (ini_get('session.auto_start')) {
1146  $phpReport[] = array(
1147  'severity' => 'failure',
1148  'message' => _elgg_services()->translator->translate("install:check:php:session.auto_start")
1149  );
1150  }
1151  }
1152 
1160  protected function checkRewriteRules(&$report) {
1161 
1162 
1163  $tester = new ElggRewriteTester();
1164  $url = _elgg_services()->config->getSiteUrl() . "rewrite.php";
1165  $report['rewrite'] = array($tester->run($url, Directory\Local::root()->getPath()));
1166  }
1167 
1174  protected function processRewriteTest() {
1175  if (strpos($_SERVER['REQUEST_URI'], 'rewrite.php') !== FALSE) {
1176  echo \Elgg\Application::REWRITE_TEST_OUTPUT;
1177  exit;
1178  }
1179  }
1180 
1189  protected function countNumConditions($report, $condition) {
1190  $count = 0;
1191  foreach ($report as $category => $checks) {
1192  foreach ($checks as $check) {
1193  if ($check['severity'] === $condition) {
1194  $count++;
1195  }
1196  }
1197  }
1198 
1199  return $count;
1200  }
1201 
1202 
1215  protected function validateDatabaseVars($submissionVars, $formVars) {
1216 
1217  foreach ($formVars as $field => $info) {
1218  if ($info['required'] == TRUE && !$submissionVars[$field]) {
1219  $name = _elgg_services()->translator->translate("install:database:label:$field");
1220  register_error(_elgg_services()->translator->translate('install:error:requiredfield', array($name)));
1221  return FALSE;
1222  }
1223  }
1224 
1225  // according to postgres documentation: SQL identifiers and key words must
1226  // begin with a letter (a-z, but also letters with diacritical marks and
1227  // non-Latin letters) or an underscore (_). Subsequent characters in an
1228  // identifier or key word can be letters, underscores, digits (0-9), or dollar signs ($).
1229  // Refs #4994
1230  if (!preg_match("/^[a-zA-Z_][\w]*$/", $submissionVars['dbprefix'])) {
1231  register_error(_elgg_services()->translator->translate('install:error:database_prefix'));
1232  return FALSE;
1233  }
1234 
1235  return $this->checkDatabaseSettings(
1236  $submissionVars['dbuser'],
1237  $submissionVars['dbpassword'],
1238  $submissionVars['dbname'],
1239  $submissionVars['dbhost']
1240  );
1241  }
1242 
1253  protected function checkDatabaseSettings($user, $password, $dbname, $host) {
1254  $config = new \Elgg\Database\Config((object)[
1255  'dbhost' => $host,
1256  'dbuser' => $user,
1257  'dbpass' => $password,
1258  'dbname' => $dbname,
1259  ]);
1260  $db = new \Elgg\Database($config);
1261 
1262  try {
1263  $db->getDataRow("SELECT 1");
1264  } catch (DatabaseException $e) {
1265  if (0 === strpos($e->getMessage(), "Elgg couldn't connect")) {
1266  register_error(_elgg_services()->translator->translate('install:error:databasesettings'));
1267  } else {
1268  register_error(_elgg_services()->translator->translate('install:error:nodatabase', array($dbname)));
1269  }
1270  return FALSE;
1271  }
1272 
1273  // check MySQL version - must be 5.0 or >
1274  $version = $db->getServerVersion(\Elgg\Database\Config::READ_WRITE);
1275  $required_version = 5.0;
1276  $points = explode('.', $version);
1277  if ($points[0] < $required_version) {
1278  register_error(_elgg_services()->translator->translate('install:error:oldmysql', array($version)));
1279  return FALSE;
1280  }
1281 
1282  return TRUE;
1283  }
1284 
1292  protected function createSettingsFile($params) {
1293  $template = \Elgg\Application::elggDir()->getContents("elgg-config/settings.example.php");
1294  if (!$template) {
1295  register_error(_elgg_services()->translator->translate('install:error:readsettingsphp'));
1296  return FALSE;
1297  }
1298 
1299  foreach ($params as $k => $v) {
1300  $template = str_replace("{{" . $k . "}}", $v, $template);
1301  }
1302 
1303  $result = file_put_contents($this->getSettingsPath(), $template);
1304  if (!$result) {
1305  register_error(_elgg_services()->translator->translate('install:error:writesettingphp'));
1306  return FALSE;
1307  }
1308 
1309  return TRUE;
1310  }
1311 
1317  protected function connectToDatabase() {
1318  if (!include_once($this->getSettingsPath())) {
1319  register_error('Elgg could not load the settings file. It does not exist or there is a file permissions issue.');
1320  return FALSE;
1321  }
1322 
1323  if (!include_once(\Elgg\Application::elggDir()->getPath("engine/lib/database.php"))) {
1324  register_error('Could not load database.php');
1325  return FALSE;
1326  }
1327 
1328  try {
1329  _elgg_services()->db->setupConnections();
1330  } catch (DatabaseException $e) {
1331  register_error($e->getMessage());
1332  return FALSE;
1333  }
1334 
1335  return TRUE;
1336  }
1337 
1343  protected function installDatabase() {
1344 
1345 
1346  try {
1347  _elgg_services()->db->runSqlScript(\Elgg\Application::elggDir()->getPath("/engine/schema/mysql.sql"));
1348  } catch (Exception $e) {
1349  $msg = $e->getMessage();
1350  if (strpos($msg, 'already exists')) {
1351  $msg = _elgg_services()->translator->translate('install:error:tables_exist');
1352  }
1353  register_error($msg);
1354  return FALSE;
1355  }
1356 
1357  return TRUE;
1358  }
1359 
1372  protected function createDataDirectory(&$submissionVars, $formVars) {
1373  // did the user have option of Elgg creating the data directory
1374  if ($formVars['dataroot']['type'] != 'combo') {
1375  return TRUE;
1376  }
1377 
1378  // did the user select the option
1379  if ($submissionVars['dataroot'] != 'dataroot-checkbox') {
1380  return TRUE;
1381  }
1382 
1383  $dir = sanitise_filepath($submissionVars['path']) . 'data';
1384  if (file_exists($dir) || mkdir($dir, 0700)) {
1385  $submissionVars['dataroot'] = $dir;
1386  if (!file_exists("$dir/.htaccess")) {
1387  $htaccess = "Order Deny,Allow\nDeny from All\n";
1388  if (!file_put_contents("$dir/.htaccess", $htaccess)) {
1389  return FALSE;
1390  }
1391  }
1392  return TRUE;
1393  }
1394 
1395  return FALSE;
1396  }
1397 
1406  protected function validateSettingsVars($submissionVars, $formVars) {
1407 
1408 
1409  foreach ($formVars as $field => $info) {
1410  $submissionVars[$field] = trim($submissionVars[$field]);
1411  if ($info['required'] == TRUE && $submissionVars[$field] === '') {
1412  $name = _elgg_services()->translator->translate("install:settings:label:$field");
1413  register_error(_elgg_services()->translator->translate('install:error:requiredfield', array($name)));
1414  return FALSE;
1415  }
1416  }
1417 
1418  // check that data root is absolute path
1419  if (stripos(PHP_OS, 'win') === 0) {
1420  if (strpos($submissionVars['dataroot'], ':') !== 1) {
1421  $msg = _elgg_services()->translator->translate('install:error:relative_path', array($submissionVars['dataroot']));
1422  register_error($msg);
1423  return FALSE;
1424  }
1425  } else {
1426  if (strpos($submissionVars['dataroot'], '/') !== 0) {
1427  $msg = _elgg_services()->translator->translate('install:error:relative_path', array($submissionVars['dataroot']));
1428  register_error($msg);
1429  return FALSE;
1430  }
1431  }
1432 
1433  // check that data root exists
1434  if (!file_exists($submissionVars['dataroot'])) {
1435  $msg = _elgg_services()->translator->translate('install:error:datadirectoryexists', array($submissionVars['dataroot']));
1436  register_error($msg);
1437  return FALSE;
1438  }
1439 
1440  // check that data root is writable
1441  if (!is_writable($submissionVars['dataroot'])) {
1442  $msg = _elgg_services()->translator->translate('install:error:writedatadirectory', array($submissionVars['dataroot']));
1443  register_error($msg);
1444  return FALSE;
1445  }
1446 
1447  if (!isset($this->CONFIG->data_dir_override) || !$this->CONFIG->data_dir_override) {
1448  // check that data root is not subdirectory of Elgg root
1449  if (stripos($submissionVars['dataroot'], $submissionVars['path']) === 0) {
1450  $msg = _elgg_services()->translator->translate('install:error:locationdatadirectory', array($submissionVars['dataroot']));
1451  register_error($msg);
1452  return FALSE;
1453  }
1454  }
1455 
1456  // check that email address is email address
1457  if ($submissionVars['siteemail'] && !is_email_address($submissionVars['siteemail'])) {
1458  $msg = _elgg_services()->translator->translate('install:error:emailaddress', array($submissionVars['siteemail']));
1459  register_error($msg);
1460  return FALSE;
1461  }
1462 
1463  // @todo check that url is a url
1464  // @note filter_var cannot be used because it doesn't work on international urls
1465 
1466  return TRUE;
1467  }
1468 
1476  protected function saveSiteSettings($submissionVars) {
1477 
1478 
1479  // ensure that file path, data path, and www root end in /
1480  $submissionVars['dataroot'] = sanitise_filepath($submissionVars['dataroot']);
1481  $submissionVars['wwwroot'] = sanitise_filepath($submissionVars['wwwroot']);
1482 
1483  $site = new ElggSite();
1484  $site->name = strip_tags($submissionVars['sitename']);
1485  $site->url = $submissionVars['wwwroot'];
1486  $site->access_id = ACCESS_PUBLIC;
1487  $site->email = $submissionVars['siteemail'];
1488  $guid = $site->save();
1489 
1490  if (!$guid) {
1491  register_error(_elgg_services()->translator->translate('install:error:createsite'));
1492  return FALSE;
1493  }
1494 
1495  // bootstrap site info
1496  $this->CONFIG->site_guid = $guid;
1497  $this->CONFIG->site_id = $guid;
1498  $this->CONFIG->site = $site;
1499 
1500  _elgg_services()->datalist->set('installed', time());
1501  _elgg_services()->datalist->set('dataroot', $submissionVars['dataroot']);
1502  _elgg_services()->datalist->set('default_site', $site->getGUID());
1503  _elgg_services()->datalist->set('version', elgg_get_version());
1504  _elgg_services()->datalist->set('simplecache_enabled', 1);
1505  _elgg_services()->datalist->set('system_cache_enabled', 1);
1506  _elgg_services()->datalist->set('simplecache_lastupdate', time());
1507 
1508  // new installations have run all the upgrades
1509  $upgrades = elgg_get_upgrade_files(\Elgg\Application::elggDir()->getPath("/engine/lib/upgrades/"));
1510  _elgg_services()->datalist->set('processed_upgrades', serialize($upgrades));
1511 
1512  _elgg_services()->configTable->set('view', 'default', $site->getGUID());
1513  _elgg_services()->configTable->set('language', 'en', $site->getGUID());
1514  _elgg_services()->configTable->set('default_access', $submissionVars['siteaccess'], $site->getGUID());
1515  _elgg_services()->configTable->set('allow_registration', TRUE, $site->getGUID());
1516  _elgg_services()->configTable->set('walled_garden', FALSE, $site->getGUID());
1517  _elgg_services()->configTable->set('allow_user_default_access', '', $site->getGUID());
1518  _elgg_services()->configTable->set('default_limit', 10, $site->getGUID());
1519 
1520  $this->setSubtypeClasses();
1521 
1522  $this->enablePlugins();
1523 
1524  return TRUE;
1525  }
1526 
1532  protected function setSubtypeClasses() {
1533  add_subtype("object", "plugin", "ElggPlugin");
1534  add_subtype("object", "file", "ElggFile");
1535  add_subtype("object", "widget", "ElggWidget");
1536  add_subtype("object", "comment", "ElggComment");
1537  add_subtype("object", "elgg_upgrade", 'ElggUpgrade');
1538  }
1539 
1545  protected function enablePlugins() {
1547  $plugins = elgg_get_plugins('any');
1548  foreach ($plugins as $plugin) {
1549  if ($plugin->getManifest()) {
1550  if ($plugin->getManifest()->getActivateOnInstall()) {
1551  $plugin->activate();
1552  }
1553  if (in_array('theme', $plugin->getManifest()->getCategories())) {
1554  $plugin->setPriority('last');
1555  }
1556  }
1557  }
1558  }
1559 
1572  protected function validateAdminVars($submissionVars, $formVars) {
1573 
1574  foreach ($formVars as $field => $info) {
1575  if ($info['required'] == TRUE && !$submissionVars[$field]) {
1576  $name = _elgg_services()->translator->translate("install:admin:label:$field");
1577  register_error(_elgg_services()->translator->translate('install:error:requiredfield', array($name)));
1578  return FALSE;
1579  }
1580  }
1581 
1582  if ($submissionVars['password1'] !== $submissionVars['password2']) {
1583  register_error(_elgg_services()->translator->translate('install:admin:password:mismatch'));
1584  return FALSE;
1585  }
1586 
1587  if (trim($submissionVars['password1']) == "") {
1588  register_error(_elgg_services()->translator->translate('install:admin:password:empty'));
1589  return FALSE;
1590  }
1591 
1592  $minLength = _elgg_services()->configTable->get('min_password_length');
1593  if (strlen($submissionVars['password1']) < $minLength) {
1594  register_error(_elgg_services()->translator->translate('install:admin:password:tooshort'));
1595  return FALSE;
1596  }
1597 
1598  // check that email address is email address
1599  if ($submissionVars['email'] && !is_email_address($submissionVars['email'])) {
1600  $msg = _elgg_services()->translator->translate('install:error:emailaddress', array($submissionVars['email']));
1601  register_error($msg);
1602  return FALSE;
1603  }
1604 
1605  return TRUE;
1606  }
1607 
1616  protected function createAdminAccount($submissionVars, $login = FALSE) {
1617  try {
1618  $guid = register_user(
1619  $submissionVars['username'],
1620  $submissionVars['password1'],
1621  $submissionVars['displayname'],
1622  $submissionVars['email']
1623  );
1624  } catch (Exception $e) {
1625  register_error($e->getMessage());
1626  return false;
1627  }
1628 
1629  if (!$guid) {
1630  register_error(_elgg_services()->translator->translate('install:admin:cannot_create'));
1631  return false;
1632  }
1633 
1634  $user = get_entity($guid);
1635  if (!$user instanceof ElggUser) {
1636  register_error(_elgg_services()->translator->translate('install:error:loadadmin'));
1637  return false;
1638  }
1639 
1640  elgg_set_ignore_access(TRUE);
1641  if ($user->makeAdmin() == FALSE) {
1642  register_error(_elgg_services()->translator->translate('install:error:adminaccess'));
1643  } else {
1644  _elgg_services()->datalist->set('admin_registered', 1);
1645  }
1646  elgg_set_ignore_access(false);
1647 
1648  // add validation data to satisfy user validation plugins
1649  create_metadata($guid, 'validated', TRUE, '', 0, ACCESS_PUBLIC);
1650  create_metadata($guid, 'validated_method', 'admin_user', '', 0, ACCESS_PUBLIC);
1651 
1652  if ($login) {
1654 
1655  // session.cache_limiter is unfortunately set to "" by the NativeSessionStorage constructor,
1656  // so we must capture and inject it directly.
1657  $options = [
1658  'cache_limiter' => session_cache_limiter(),
1659  ];
1661 
1662  $session = new ElggSession(new Symfony\Component\HttpFoundation\Session\Session($storage));
1663  $session->setName('Elgg');
1664  _elgg_services()->setValue('session', $session);
1665  if (login($user) == FALSE) {
1666  register_error(_elgg_services()->translator->translate('install:error:adminlogin'));
1667  }
1668  }
1669 
1670  return TRUE;
1671  }
1672 }
checkSettingsFile(&$report=array())
Check that the settings file exists.
A simple directory abstraction.
Definition: Directory.php:13
$extensions
Definition: summary.php:41
$plugin
elgg_get_upgrade_files($upgrade_path=null)
Returns a list of upgrade files relative to the $upgrade_path dir.
Definition: upgrade.php:52
batchInstall(array $params, $createHtaccess=FALSE)
A batch install of Elgg.
createDataDirectory(&$submissionVars, $formVars)
Site settings support methods.
if(!array_key_exists($filename, $text_files)) $file
setSubtypeClasses()
Register classes for core objects.
bootstrapEngine()
Bootstraping.
$version
$table
Definition: cron.php:34
countNumConditions($report, $condition)
Count the number of failures in the requirements report.
processRewriteTest()
Check if the request is coming from the URL rewrite test on the requirements page.
if($guid==elgg_get_logged_in_user_guid()) $name
Definition: delete.php:21
create_metadata($entity_guid, $name, $value, $value_type= '', $owner_guid=0, $access_id=null, $allow_multiple=false)
Create a new metadata object, or update an existing one.
Definition: metadata.php:66
finishBootstraping($step)
Load remaining engine libraries and complete bootstraping (see start.php)
$e
Definition: metadata.php:12
checkPhpDirectives(&$phpReport)
Check PHP parameters.
$lang
Definition: html.php:12
welcome($vars)
Step controllers.
$defaults
sanitise_filepath($path, $append_slash=true)
Sanitise file paths ensuring that they begin and end with slashes etc.
Definition: elgglib.php:411
$_ELGG translations
String translations for the current language.
Definition: config.php:333
$path
Definition: details.php:88
$value
Definition: longtext.php:42
setInstallStatus()
Check the different install steps for completion.
installDatabase()
Create the database tables.
checkInstallCompletion($step)
Security check to ensure the installer cannot be run after installation has finished.
getNextStep($currentStep)
Get the next step as a string.
$guid
Removes an admin notice.
requirements($vars)
Requirements controller.
elgg forward
Meant to mimic the php forward() function by simply redirecting the user to another page...
Definition: elgglib.js:425
getSteps()
Step management.
$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
$report
if($screenshots) $info
Definition: details.php:58
$url
Definition: exceptions.php:24
$vars['entity']
checkPHP(&$report)
Check version of PHP, extensions, and variables.
$title
Definition: save.php:22
and that you know you can do these things To protect your we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights These restrictions translate to certain responsibilities for you if you distribute copies of the or if you modify it For if you distribute copies of such a whether gratis or for a you must give the recipients all the rights that you have You must make sure that receive or can get the source code And you must show them these terms so they know their rights We protect your rights with two steps
Definition: GPL-LICENSE.txt:28
$options
Elgg admin footer.
Definition: footer.php:6
validateSettingsVars($submissionVars, $formVars)
Validate the site settings form variables.
resumeInstall($step)
Check if this is a case of a install being resumed and figure out where to continue from...
$params
Definition: login.php:72
is_email_address($address)
Validates an email address.
Definition: input.php:88
settings($submissionVars)
Site settings controller.
continueToNextStep($currentStep)
Forwards the browser to the next step.
getPath($path= '')
Get the absolute path to the given directory-relative path.
render($step, $vars=array())
Renders the data passed by a controller.
Save menu items.
getNextStepUrl($currentStep)
Get the URL of the next step.
add_subtype($type, $subtype, $class="")
Register with a certain type and subtype to be loaded as a specific class.
Definition: entities.php:95
getBaseUrl()
Get the best guess at the base URL.
$key
Definition: summary.php:34
elgg_set_ignore_access($ignore=true)
Set if Elgg&#39;s access system should be ignored.
Definition: access.php:43
makeFormSticky($formVars, $submissionVars)
If form is reshown, remember previously submitted variables.
$user
Definition: ban.php:13
if(elgg_extract('required', $vars)) $field
Definition: field.php:25
elgg_set_viewtype($viewtype="")
Manually set the viewtype.
Definition: views.php:74
elgg echo
Translates a string.
Definition: languages.js:48
checkPhpExtensions(&$phpReport)
Check the server&#39;s PHP extensions.
elgg_view($view, $vars=array(), $ignore1=false, $ignore2=false, $viewtype= '')
Return a parsed view.
Definition: views.php:336
elgg global
Pointer to the global context.
Definition: elgglib.js:12
bootstrapConfig()
Set up configuration variables.
_elgg_services(\Elgg\Di\ServiceProvider $services=null)
Get the global service provider.
Definition: autoloader.php:17
checkRewriteRules(&$report)
Confirm that the rewrite rules are firing.
$password
Definition: login.php:25
validateDatabaseVars($submissionVars, $formVars)
Database support methods.
elgg system_message
Wrapper function for system_messages.
Definition: elgglib.js:390
createSettingsFile($params)
Writes the settings file to the engine directory.
enablePlugins()
Enable a set of default plugins.
elgg_get_plugins($status= 'active', $site_guid=null)
Returns an ordered list of plugins.
Definition: plugins.php:132
const ACCESS_PUBLIC
Definition: elgglib.php:2084
elgg subtext time
elgg_get_version($human_readable=false)
Get the current Elgg version information.
Definition: elgglib.php:1071
complete()
Controller for last step.
elgg register_error
Wrapper function for system_messages.
Definition: elgglib.js:399
isInstallDirWritable(&$report)
Requirement checks support methods.
getPostVariables()
Action handling methods.
loadSettingsFile()
Load settings.php.
__construct()
Constructor bootstraps the Elgg engine.
var sprintf
sprintf() for JavaScript 0.7-beta1 http://www.diveintojavascript.com/projects/javascript-sprintf ...
Definition: sprintf.js:61
admin($submissionVars)
Admin account controller.
login(\ElggUser $user, $persistent=false)
Logs in a specified .
Definition: sessions.php:320
checkDatabaseSettings($user, $password, $dbname, $host)
Confirm the settings for the database.
static elggDir()
Returns a directory that points to the root of Elgg, but not necessarily the install root...
if(elgg_in_context('widget')) $count
Definition: pagination.php:21
createAdminAccount($submissionVars, $login=FALSE)
Create a user account for the admin.
static getMock()
Get an isolated ElggSession that does not persist between requests.
connectToDatabase()
Bootstrap database connection before entire engine is available.
setAutoLogin($flag)
Set the auto login flag.
$index
Definition: gallery.php:49
exit
Definition: autoloader.php:34
$handler
Definition: add.php:10
saveSiteSettings($submissionVars)
Initialize the site including site entity, plugins, and configuration.
_elgg_session_boot()
Initializes the session and checks for the remember me cookie.
Definition: sessions.php:401
$session
Definition: login.php:9
database($submissionVars)
Database set up controller.
http free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:5
run($step)
Dispatches a request to one of the step controllers.
_elgg_generate_plugin_entities()
Discovers plugins in the plugins_path setting and creates entities for them if they don&#39;t exist...
Definition: plugins.php:60
$extension
Definition: default.php:23
get_entity($guid)
Loads and returns an entity object from a guid.
Definition: entities.php:204
elgg_view_page($title, $body, $page_shell= 'default', $vars=array())
Assembles and outputs a full page.
Definition: views.php:447
validateAdminVars($submissionVars, $formVars)
Admin account support methods.