Elgg  Version 1.11
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', \ElggSession::getMock());
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 
856  // required by elgg_view_page()
857  $this->CONFIG->sitename = '';
858  $this->CONFIG->sitedescription = '';
859 
860  // required by Elgg\Config::get
861  $this->CONFIG->site_guid = 1;
862  }
863 
867  private function isHttps() {
868  return (!empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") ||
869  $_SERVER['SERVER_PORT'] == 443;
870  }
871 
880  protected function getBaseUrl() {
881  $protocol = $this->isHttps() ? 'https' : 'http';
882 
883  if (isset($_SERVER["SERVER_PORT"])) {
884  $port = ':' . $_SERVER["SERVER_PORT"];
885  } else {
886  $port = '';
887  }
888  if ($port == ':80' || $port == ':443') {
889  $port = '';
890  }
891  $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
892  $cutoff = strpos($uri, 'install.php');
893  $uri = substr($uri, 0, $cutoff);
894  $serverName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
895 
896  return "$protocol://{$serverName}$port{$uri}";
897  }
898 
905  protected function loadSettingsFile() {
906 
907 
908  if (!include_once("{$this->CONFIG->path}engine/settings.php")) {
909  throw new InstallationException(_elgg_services()->translator->translate('InstallationException:CannotLoadSettings'));
910  }
911  }
912 
926  protected function getPostVariables() {
927  $vars = array();
928  foreach ($_POST as $k => $v) {
929  $vars[$k] = $v;
930  }
931  return $vars;
932  }
933 
942  protected function makeFormSticky($formVars, $submissionVars) {
943  foreach ($submissionVars as $field => $value) {
944  $formVars[$field]['value'] = $value;
945  }
946  return $formVars;
947  }
948 
960  protected function checkEngineDir(&$report) {
961 
962 
963  $writable = is_writable("{$this->CONFIG->path}engine");
964  if (!$writable) {
965  $report['settings'] = array(
966  array(
967  'severity' => 'failure',
968  'message' => _elgg_services()->translator->translate('install:check:enginedir'),
969  )
970  );
971  return FALSE;
972  }
973 
974  return TRUE;
975  }
976 
984  protected function checkSettingsFile(&$report = array()) {
985 
986 
987  if (!file_exists("{$this->CONFIG->path}engine/settings.php")) {
988  return FALSE;
989  }
990 
991  if (!is_readable("{$this->CONFIG->path}engine/settings.php")) {
992  $report['settings'] = array(
993  array(
994  'severity' => 'failure',
995  'message' => _elgg_services()->translator->translate('install:check:readsettings'),
996  )
997  );
998  }
999 
1000  return TRUE;
1001  }
1002 
1010  protected function checkPHP(&$report) {
1011  $phpReport = array();
1012 
1013  $min_php_version = '5.4.0';
1014  if (version_compare(PHP_VERSION, $min_php_version, '<')) {
1015  $phpReport[] = array(
1016  'severity' => 'failure',
1017  'message' => _elgg_services()->translator->translate('install:check:php:version', array($min_php_version, PHP_VERSION))
1018  );
1019  }
1020 
1021  $this->checkPhpExtensions($phpReport);
1022 
1023  $this->checkPhpDirectives($phpReport);
1024 
1025  if (count($phpReport) == 0) {
1026  $phpReport[] = array(
1027  'severity' => 'pass',
1028  'message' => _elgg_services()->translator->translate('install:check:php:success')
1029  );
1030  }
1031 
1032  $report['php'] = $phpReport;
1033  }
1034 
1042  protected function checkPhpExtensions(&$phpReport) {
1043  $extensions = get_loaded_extensions();
1044  $requiredExtensions = array(
1045  'mysql',
1046  'json',
1047  'xml',
1048  'gd',
1049  );
1050  foreach ($requiredExtensions as $extension) {
1051  if (!in_array($extension, $extensions)) {
1052  $phpReport[] = array(
1053  'severity' => 'failure',
1054  'message' => _elgg_services()->translator->translate('install:check:php:extension', array($extension))
1055  );
1056  }
1057  }
1058 
1059  $recommendedExtensions = array(
1060  'mbstring',
1061  );
1062  foreach ($recommendedExtensions as $extension) {
1063  if (!in_array($extension, $extensions)) {
1064  $phpReport[] = array(
1065  'severity' => 'warning',
1066  'message' => _elgg_services()->translator->translate('install:check:php:extension:recommend', array($extension))
1067  );
1068  }
1069  }
1070  }
1071 
1079  protected function checkPhpDirectives(&$phpReport) {
1080  if (ini_get('open_basedir')) {
1081  $phpReport[] = array(
1082  'severity' => 'warning',
1083  'message' => _elgg_services()->translator->translate("install:check:php:open_basedir")
1084  );
1085  }
1086 
1087  if (ini_get('safe_mode')) {
1088  $phpReport[] = array(
1089  'severity' => 'warning',
1090  'message' => _elgg_services()->translator->translate("install:check:php:safe_mode")
1091  );
1092  }
1093 
1094  if (ini_get('arg_separator.output') !== '&') {
1095  $separator = htmlspecialchars(ini_get('arg_separator.output'));
1096  $msg = _elgg_services()->translator->translate("install:check:php:arg_separator", array($separator));
1097  $phpReport[] = array(
1098  'severity' => 'failure',
1099  'message' => $msg,
1100  );
1101  }
1102 
1103  if (ini_get('register_globals')) {
1104  $phpReport[] = array(
1105  'severity' => 'failure',
1106  'message' => _elgg_services()->translator->translate("install:check:php:register_globals")
1107  );
1108  }
1109 
1110  if (ini_get('session.auto_start')) {
1111  $phpReport[] = array(
1112  'severity' => 'failure',
1113  'message' => _elgg_services()->translator->translate("install:check:php:session.auto_start")
1114  );
1115  }
1116  }
1117 
1125  protected function checkRewriteRules(&$report) {
1126 
1127 
1128  $tester = new ElggRewriteTester();
1129  $url = _elgg_services()->config->getSiteUrl() . "rewrite.php";
1130  $report['rewrite'] = array($tester->run($url, $this->CONFIG->path));
1131  }
1132 
1139  protected function processRewriteTest() {
1140  if (strpos($_SERVER['REQUEST_URI'], 'rewrite.php') !== FALSE) {
1141  echo 'success';
1142  exit;
1143  }
1144  }
1145 
1154  protected function countNumConditions($report, $condition) {
1155  $count = 0;
1156  foreach ($report as $category => $checks) {
1157  foreach ($checks as $check) {
1158  if ($check['severity'] === $condition) {
1159  $count++;
1160  }
1161  }
1162  }
1163 
1164  return $count;
1165  }
1166 
1167 
1180  protected function validateDatabaseVars($submissionVars, $formVars) {
1181 
1182  foreach ($formVars as $field => $info) {
1183  if ($info['required'] == TRUE && !$submissionVars[$field]) {
1184  $name = _elgg_services()->translator->translate("install:database:label:$field");
1185  register_error(_elgg_services()->translator->translate('install:error:requiredfield', array($name)));
1186  return FALSE;
1187  }
1188  }
1189 
1190  // according to postgres documentation: SQL identifiers and key words must
1191  // begin with a letter (a-z, but also letters with diacritical marks and
1192  // non-Latin letters) or an underscore (_). Subsequent characters in an
1193  // identifier or key word can be letters, underscores, digits (0-9), or dollar signs ($).
1194  // Refs #4994
1195  if (!preg_match("/^[a-zA-Z_][\w]*$/", $submissionVars['dbprefix'])) {
1196  register_error(_elgg_services()->translator->translate('install:error:database_prefix'));
1197  return FALSE;
1198  }
1199 
1200  return $this->checkDatabaseSettings(
1201  $submissionVars['dbuser'],
1202  $submissionVars['dbpassword'],
1203  $submissionVars['dbname'],
1204  $submissionVars['dbhost']
1205  );
1206  }
1207 
1218  protected function checkDatabaseSettings($user, $password, $dbname, $host) {
1219  $config = new \Elgg\Database\Config((object)[
1220  'dbhost' => $host,
1221  'dbuser' => $user,
1222  'dbpass' => $password,
1223  'dbname' => $dbname,
1224  ]);
1225  $logger = new \Elgg\Logger(new \Elgg\PluginHooksService());
1226  $db = new \Elgg\Database($config, $logger);
1227 
1228  try {
1229  $db->getDataRow("SELECT 1");
1230  } catch (DatabaseException $e) {
1231  if (0 === strpos($e->getMessage(), "Elgg couldn't connect")) {
1232  register_error(_elgg_services()->translator->translate('install:error:databasesettings'));
1233  } else {
1234  register_error(_elgg_services()->translator->translate('install:error:nodatabase', array($dbname)));
1235  }
1236  return FALSE;
1237  }
1238 
1239  // check MySQL version - must be 5.0 or >
1240  $version = $db->getServerVersion(\Elgg\Database\Config::READ_WRITE);
1241  $required_version = 5.0;
1242  $points = explode('.', $version);
1243  if ($points[0] < $required_version) {
1244  register_error(_elgg_services()->translator->translate('install:error:oldmysql', array($version)));
1245  return FALSE;
1246  }
1247 
1248  return TRUE;
1249  }
1250 
1258  protected function createSettingsFile($params) {
1259 
1260 
1261  $templateFile = "{$this->CONFIG->path}engine/settings.example.php";
1262  $template = file_get_contents($templateFile);
1263  if (!$template) {
1264  register_error(_elgg_services()->translator->translate('install:error:readsettingsphp'));
1265  return FALSE;
1266  }
1267 
1268  foreach ($params as $k => $v) {
1269  $template = str_replace("{{" . $k . "}}", $v, $template);
1270  }
1271 
1272  $settingsFilename = "{$this->CONFIG->path}engine/settings.php";
1273  $result = file_put_contents($settingsFilename, $template);
1274  if (!$result) {
1275  register_error(_elgg_services()->translator->translate('install:error:writesettingphp'));
1276  return FALSE;
1277  }
1278 
1279  return TRUE;
1280  }
1281 
1287  protected function connectToDatabase() {
1288 
1289 
1290  if (!include_once("{$this->CONFIG->path}engine/settings.php")) {
1291  register_error('Elgg could not load the settings file. It does not exist or there is a file permissions issue.');
1292  return FALSE;
1293  }
1294 
1295  if (!include_once("{$this->CONFIG->path}engine/lib/database.php")) {
1296  register_error('Could not load database.php');
1297  return FALSE;
1298  }
1299 
1300  try {
1301  _elgg_services()->db->setupConnections();
1302  } catch (DatabaseException $e) {
1303  register_error($e->getMessage());
1304  return FALSE;
1305  }
1306 
1307  return TRUE;
1308  }
1309 
1315  protected function installDatabase() {
1316 
1317 
1318  try {
1319  _elgg_services()->db->runSqlScript("{$this->CONFIG->path}engine/schema/mysql.sql");
1320  } catch (Exception $e) {
1321  $msg = $e->getMessage();
1322  if (strpos($msg, 'already exists')) {
1323  $msg = _elgg_services()->translator->translate('install:error:tables_exist');
1324  }
1325  register_error($msg);
1326  return FALSE;
1327  }
1328 
1329  return TRUE;
1330  }
1331 
1344  protected function createDataDirectory(&$submissionVars, $formVars) {
1345  // did the user have option of Elgg creating the data directory
1346  if ($formVars['dataroot']['type'] != 'combo') {
1347  return TRUE;
1348  }
1349 
1350  // did the user select the option
1351  if ($submissionVars['dataroot'] != 'dataroot-checkbox') {
1352  return TRUE;
1353  }
1354 
1355  $dir = sanitise_filepath($submissionVars['path']) . 'data';
1356  if (file_exists($dir) || mkdir($dir, 0700)) {
1357  $submissionVars['dataroot'] = $dir;
1358  if (!file_exists("$dir/.htaccess")) {
1359  $htaccess = "Order Deny,Allow\nDeny from All\n";
1360  if (!file_put_contents("$dir/.htaccess", $htaccess)) {
1361  return FALSE;
1362  }
1363  }
1364  return TRUE;
1365  }
1366 
1367  return FALSE;
1368  }
1369 
1378  protected function validateSettingsVars($submissionVars, $formVars) {
1379 
1380 
1381  foreach ($formVars as $field => $info) {
1382  $submissionVars[$field] = trim($submissionVars[$field]);
1383  if ($info['required'] == TRUE && $submissionVars[$field] === '') {
1384  $name = _elgg_services()->translator->translate("install:settings:label:$field");
1385  register_error(_elgg_services()->translator->translate('install:error:requiredfield', array($name)));
1386  return FALSE;
1387  }
1388  }
1389 
1390  // check that data root is absolute path
1391  if (stripos(PHP_OS, 'win') === 0) {
1392  if (strpos($submissionVars['dataroot'], ':') !== 1) {
1393  $msg = _elgg_services()->translator->translate('install:error:relative_path', array($submissionVars['dataroot']));
1394  register_error($msg);
1395  return FALSE;
1396  }
1397  } else {
1398  if (strpos($submissionVars['dataroot'], '/') !== 0) {
1399  $msg = _elgg_services()->translator->translate('install:error:relative_path', array($submissionVars['dataroot']));
1400  register_error($msg);
1401  return FALSE;
1402  }
1403  }
1404 
1405  // check that data root exists
1406  if (!file_exists($submissionVars['dataroot'])) {
1407  $msg = _elgg_services()->translator->translate('install:error:datadirectoryexists', array($submissionVars['dataroot']));
1408  register_error($msg);
1409  return FALSE;
1410  }
1411 
1412  // check that data root is writable
1413  if (!is_writable($submissionVars['dataroot'])) {
1414  $msg = _elgg_services()->translator->translate('install:error:writedatadirectory', array($submissionVars['dataroot']));
1415  register_error($msg);
1416  return FALSE;
1417  }
1418 
1419  if (!isset($this->CONFIG->data_dir_override) || !$this->CONFIG->data_dir_override) {
1420  // check that data root is not subdirectory of Elgg root
1421  if (stripos($submissionVars['dataroot'], $submissionVars['path']) === 0) {
1422  $msg = _elgg_services()->translator->translate('install:error:locationdatadirectory', array($submissionVars['dataroot']));
1423  register_error($msg);
1424  return FALSE;
1425  }
1426  }
1427 
1428  // check that email address is email address
1429  if ($submissionVars['siteemail'] && !is_email_address($submissionVars['siteemail'])) {
1430  $msg = _elgg_services()->translator->translate('install:error:emailaddress', array($submissionVars['siteemail']));
1431  register_error($msg);
1432  return FALSE;
1433  }
1434 
1435  // @todo check that url is a url
1436  // @note filter_var cannot be used because it doesn't work on international urls
1437 
1438  return TRUE;
1439  }
1440 
1448  protected function saveSiteSettings($submissionVars) {
1449 
1450 
1451  // ensure that file path, data path, and www root end in /
1452  $submissionVars['dataroot'] = sanitise_filepath($submissionVars['dataroot']);
1453  $submissionVars['wwwroot'] = sanitise_filepath($submissionVars['wwwroot']);
1454 
1455  $site = new ElggSite();
1456  $site->name = strip_tags($submissionVars['sitename']);
1457  $site->url = $submissionVars['wwwroot'];
1458  $site->access_id = ACCESS_PUBLIC;
1459  $site->email = $submissionVars['siteemail'];
1460  $guid = $site->save();
1461 
1462  if (!$guid) {
1463  register_error(_elgg_services()->translator->translate('install:error:createsite'));
1464  return FALSE;
1465  }
1466 
1467  // bootstrap site info
1468  $this->CONFIG->site_guid = $guid;
1469  $this->CONFIG->site_id = $guid;
1470  $this->CONFIG->site = $site;
1471 
1472  _elgg_services()->datalist->set('installed', time());
1473  _elgg_services()->datalist->set('dataroot', $submissionVars['dataroot']);
1474  _elgg_services()->datalist->set('default_site', $site->getGUID());
1475  _elgg_services()->datalist->set('version', elgg_get_version());
1476  _elgg_services()->datalist->set('simplecache_enabled', 1);
1477  _elgg_services()->datalist->set('system_cache_enabled', 1);
1478  _elgg_services()->datalist->set('simplecache_lastupdate', time());
1479 
1480  // @todo plugins might use this, but core doesn't. remove in 2.0
1481  _elgg_services()->datalist->set('path', $this->CONFIG->path);
1482 
1483  // new installations have run all the upgrades
1484  $upgrades = elgg_get_upgrade_files("{$this->CONFIG->path}engine/lib/upgrades/");
1485  _elgg_services()->datalist->set('processed_upgrades', serialize($upgrades));
1486 
1487  _elgg_services()->configTable->set('view', 'default', $site->getGUID());
1488  _elgg_services()->configTable->set('language', 'en', $site->getGUID());
1489  _elgg_services()->configTable->set('default_access', $submissionVars['siteaccess'], $site->getGUID());
1490  _elgg_services()->configTable->set('allow_registration', TRUE, $site->getGUID());
1491  _elgg_services()->configTable->set('walled_garden', FALSE, $site->getGUID());
1492  _elgg_services()->configTable->set('allow_user_default_access', '', $site->getGUID());
1493  _elgg_services()->configTable->set('default_limit', 10, $site->getGUID());
1494 
1495  $this->setSubtypeClasses();
1496 
1497  $this->enablePlugins();
1498 
1499  return TRUE;
1500  }
1501 
1507  protected function setSubtypeClasses() {
1508  add_subtype("object", "plugin", "ElggPlugin");
1509  add_subtype("object", "file", "ElggFile");
1510  add_subtype("object", "widget", "ElggWidget");
1511  add_subtype("object", "comment", "ElggComment");
1512  add_subtype("object", "elgg_upgrade", 'ElggUpgrade');
1513  }
1514 
1520  protected function enablePlugins() {
1522  $plugins = elgg_get_plugins('any');
1523  foreach ($plugins as $plugin) {
1524  if ($plugin->getManifest()) {
1525  if ($plugin->getManifest()->getActivateOnInstall()) {
1526  $plugin->activate();
1527  }
1528  if (in_array('theme', $plugin->getManifest()->getCategories())) {
1529  $plugin->setPriority('last');
1530  }
1531  }
1532  }
1533  }
1534 
1547  protected function validateAdminVars($submissionVars, $formVars) {
1548 
1549  foreach ($formVars as $field => $info) {
1550  if ($info['required'] == TRUE && !$submissionVars[$field]) {
1551  $name = _elgg_services()->translator->translate("install:admin:label:$field");
1552  register_error(_elgg_services()->translator->translate('install:error:requiredfield', array($name)));
1553  return FALSE;
1554  }
1555  }
1556 
1557  if ($submissionVars['password1'] !== $submissionVars['password2']) {
1558  register_error(_elgg_services()->translator->translate('install:admin:password:mismatch'));
1559  return FALSE;
1560  }
1561 
1562  if (trim($submissionVars['password1']) == "") {
1563  register_error(_elgg_services()->translator->translate('install:admin:password:empty'));
1564  return FALSE;
1565  }
1566 
1567  $minLength = _elgg_services()->configTable->get('min_password_length');
1568  if (strlen($submissionVars['password1']) < $minLength) {
1569  register_error(_elgg_services()->translator->translate('install:admin:password:tooshort'));
1570  return FALSE;
1571  }
1572 
1573  // check that email address is email address
1574  if ($submissionVars['email'] && !is_email_address($submissionVars['email'])) {
1575  $msg = _elgg_services()->translator->translate('install:error:emailaddress', array($submissionVars['email']));
1576  register_error($msg);
1577  return FALSE;
1578  }
1579 
1580  return TRUE;
1581  }
1582 
1591  protected function createAdminAccount($submissionVars, $login = FALSE) {
1592  try {
1593  $guid = register_user(
1594  $submissionVars['username'],
1595  $submissionVars['password1'],
1596  $submissionVars['displayname'],
1597  $submissionVars['email']
1598  );
1599  } catch (Exception $e) {
1600  register_error($e->getMessage());
1601  return false;
1602  }
1603 
1604  if (!$guid) {
1605  register_error(_elgg_services()->translator->translate('install:admin:cannot_create'));
1606  return false;
1607  }
1608 
1609  $user = get_entity($guid);
1610  if (!$user instanceof ElggUser) {
1611  register_error(_elgg_services()->translator->translate('install:error:loadadmin'));
1612  return false;
1613  }
1614 
1615  elgg_set_ignore_access(TRUE);
1616  if ($user->makeAdmin() == FALSE) {
1617  register_error(_elgg_services()->translator->translate('install:error:adminaccess'));
1618  } else {
1619  _elgg_services()->datalist->set('admin_registered', 1);
1620  }
1621  elgg_set_ignore_access(false);
1622 
1623  // add validation data to satisfy user validation plugins
1624  create_metadata($guid, 'validated', TRUE, '', 0, ACCESS_PUBLIC);
1625  create_metadata($guid, 'validated_method', 'admin_user', '', 0, ACCESS_PUBLIC);
1626 
1627  if ($login) {
1629 
1630  // session.cache_limiter is unfortunately set to "" by the NativeSessionStorage constructor,
1631  // so we must capture and inject it directly.
1632  $options = [
1633  'cache_limiter' => session_cache_limiter(),
1634  ];
1635  $storage = new Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage($options, $handler);
1636 
1637  $session = new ElggSession(new Symfony\Component\HttpFoundation\Session\Session($storage));
1638  $session->setName('Elgg');
1639  _elgg_services()->setValue('session', $session);
1640  if (login($user) == FALSE) {
1641  register_error(_elgg_services()->translator->translate('install:error:adminlogin'));
1642  }
1643  }
1644 
1645  return TRUE;
1646  }
1647 }
$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
$defaults
_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.
static getMock()
Get an isolated ElggSession that does not persist between requests.
$guid
Removes an admin notice.
register_error($error)
Display an error on next page load.
Definition: elgglib.php:455
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:442
elgg_get_version($human_readable=false)
Get the current Elgg version information.
Definition: elgglib.php:976
const ACCESS_PUBLIC
Definition: elgglib.php:1956
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:26
is_email_address($address)
Validates an email address.
Definition: input.php:88
$step
Definition: install.php:23
$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:9
$lib_files
Definition: load.php:25
Save menu items.
$options
Definition: index.php:14
if(elgg_in_context('widget')) $count
Definition: pagination.php:20
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
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