Elgg  Version 2.2
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 
59  private $CONFIG;
60 
64  public function __construct() {
65  global $CONFIG;
66  if (!isset($CONFIG)) {
67  $CONFIG = new stdClass;
68  }
69 
70  global $_ELGG;
71  if (!isset($_ELGG)) {
72  $_ELGG = new stdClass;
73  }
74 
75  $this->CONFIG = $CONFIG;
76 
77  $this->isAction = isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST';
78 
79  $this->bootstrapConfig();
80 
81  $this->bootstrapEngine();
82 
83  _elgg_services()->setValue('session', \ElggSession::getMock());
84 
85  elgg_set_viewtype('installation');
86 
87  set_error_handler('_elgg_php_error_handler');
88  set_exception_handler('_elgg_php_exception_handler');
89 
90  _elgg_services()->config->set('simplecache_enabled', false);
91  _elgg_services()->translator->registerTranslations(\Elgg\Application::elggDir()->getPath("/install/languages/"), TRUE);
92  _elgg_services()->views->registerPluginViews(\Elgg\Application::elggDir()->getPath("/"));
93  }
94 
103  public function run($step) {
104  global $CONFIG;
105 
106  // language needs to be set before the first call to elgg_echo()
107  $CONFIG->language = 'en';
108 
109  // check if this is a URL rewrite test coming in
110  $this->processRewriteTest();
111 
112  if (!in_array($step, $this->getSteps())) {
113  $msg = _elgg_services()->translator->translate('InstallationException:UnknownStep', array($step));
114  throw new InstallationException($msg);
115  }
116 
117  $this->setInstallStatus();
118 
119  $this->checkInstallCompletion($step);
120 
121  // check if this is an install being resumed
122  $this->resumeInstall($step);
123 
124  $this->finishBootstraping($step);
125 
126  $params = $this->getPostVariables();
127 
128  $this->$step($params);
129  }
130 
138  public function setAutoLogin($flag) {
139  $this->autoLogin = (bool) $flag;
140  }
141 
160  public function batchInstall(array $params, $createHtaccess = FALSE) {
161 
162 
163  restore_error_handler();
164  restore_exception_handler();
165 
166  $defaults = array(
167  'dbhost' => 'localhost',
168  'dbprefix' => 'elgg_',
169  'language' => 'en',
170  'siteaccess' => ACCESS_PUBLIC,
171  'site_guid' => 1,
172  );
173  $params = array_merge($defaults, $params);
174 
175  $requiredParams = array(
176  'dbuser',
177  'dbpassword',
178  'dbname',
179  'sitename',
180  'wwwroot',
181  'dataroot',
182  'displayname',
183  'email',
184  'username',
185  'password',
186  );
187  foreach ($requiredParams as $key) {
188  if (empty($params[$key])) {
189  $msg = _elgg_services()->translator->translate('install:error:requiredfield', array($key));
190  throw new InstallationException($msg);
191  }
192  }
193 
194  // password is passed in once
195  $params['password1'] = $params['password2'] = $params['password'];
196 
197  if ($createHtaccess) {
198  $rewriteTester = new ElggRewriteTester();
199  if (!$rewriteTester->createHtaccess($params['wwwroot'], Directory\Local::root()->getPath())) {
200  throw new InstallationException(_elgg_services()->translator->translate('install:error:htaccess'));
201  }
202  }
203 
204  $this->setInstallStatus();
205 
206  if (!$this->status['config']) {
207  if (!$this->createSettingsFile($params)) {
208  throw new InstallationException(_elgg_services()->translator->translate('install:error:settings'));
209  }
210  }
211 
212  if (!$this->connectToDatabase()) {
213  throw new InstallationException(_elgg_services()->translator->translate('install:error:databasesettings'));
214  }
215 
216  if (!$this->status['database']) {
217  if (!$this->installDatabase()) {
218  throw new InstallationException(_elgg_services()->translator->translate('install:error:cannotloadtables'));
219  }
220  }
221 
222  // load remaining core libraries
223  $this->finishBootstraping('settings');
224 
225  if (!$this->saveSiteSettings($params)) {
226  throw new InstallationException(_elgg_services()->translator->translate('install:error:savesitesettings'));
227  }
228 
229  if (!$this->createAdminAccount($params)) {
230  throw new InstallationException(_elgg_services()->translator->translate('install:admin:cannot_create'));
231  }
232  }
233 
242  protected function render($step, $vars = array()) {
243  $vars['next_step'] = $this->getNextStep($step);
244 
245  $title = _elgg_services()->translator->translate("install:$step");
246  $body = elgg_view("install/pages/$step", $vars);
247 
249  $title,
250  $body,
251  'default',
252  array(
253  'step' => $step,
254  'steps' => $this->getSteps(),
255  )
256  );
257  exit;
258  }
259 
271  protected function welcome($vars) {
272  $this->render('welcome');
273  }
274 
284  protected function requirements($vars) {
285 
286  $report = array();
287 
288  // check PHP parameters and libraries
289  $this->checkPHP($report);
290 
291  // check URL rewriting
292  $this->checkRewriteRules($report);
293 
294  // check for existence of settings file
295  if ($this->checkSettingsFile($report) != TRUE) {
296  // no file, so check permissions on engine directory
298  }
299 
300  // check the database later
301  $report['database'] = array(array(
302  'severity' => 'info',
303  'message' => _elgg_services()->translator->translate('install:check:database')
304  ));
305 
306  // any failures?
307  $numFailures = $this->countNumConditions($report, 'failure');
308 
309  // any warnings
310  $numWarnings = $this->countNumConditions($report, 'warning');
311 
312 
313  $params = array(
314  'report' => $report,
315  'num_failures' => $numFailures,
316  'num_warnings' => $numWarnings,
317  );
318 
319  $this->render('requirements', $params);
320  }
321 
331  protected function database($submissionVars) {
332 
333  $formVars = array(
334  'dbuser' => array(
335  'type' => 'text',
336  'value' => '',
337  'required' => TRUE,
338  ),
339  'dbpassword' => array(
340  'type' => 'password',
341  'value' => '',
342  'required' => FALSE,
343  ),
344  'dbname' => array(
345  'type' => 'text',
346  'value' => '',
347  'required' => TRUE,
348  ),
349  'dbhost' => array(
350  'type' => 'text',
351  'value' => 'localhost',
352  'required' => TRUE,
353  ),
354  'dbprefix' => array(
355  'type' => 'text',
356  'value' => 'elgg_',
357  'required' => TRUE,
358  ),
359  'timezone' => array(
360  'type' => 'dropdown',
361  'value' => 'UTC',
362  'options' => \DateTimeZone::listIdentifiers(),
363  'required' => TRUE
364  )
365  );
366 
367  if ($this->checkSettingsFile()) {
368  // user manually created settings file so we fake out action test
369  $this->isAction = TRUE;
370  }
371 
372  if ($this->isAction) {
373  do {
374  // only create settings file if it doesn't exist
375  if (!$this->checkSettingsFile()) {
376  if (!$this->validateDatabaseVars($submissionVars, $formVars)) {
377  // error so we break out of action and serve same page
378  break;
379  }
380 
381  if (!$this->createSettingsFile($submissionVars)) {
382  break;
383  }
384  }
385 
386  // check db version and connect
387  if (!$this->connectToDatabase()) {
388  break;
389  }
390 
391  if (!$this->installDatabase()) {
392  break;
393  }
394 
395  system_message(_elgg_services()->translator->translate('install:success:database'));
396 
397  $this->continueToNextStep('database');
398  } while (FALSE); // PHP doesn't support breaking out of if statements
399  }
400 
401  $formVars = $this->makeFormSticky($formVars, $submissionVars);
402 
403  $params = array('variables' => $formVars,);
404 
405  if ($this->checkSettingsFile()) {
406  // settings file exists and we're here so failed to create database
407  $params['failure'] = TRUE;
408  }
409 
410  $this->render('database', $params);
411  }
412 
422  protected function settings($submissionVars) {
423 
424 
425  $formVars = array(
426  'sitename' => array(
427  'type' => 'text',
428  'value' => 'My New Community',
429  'required' => TRUE,
430  ),
431  'siteemail' => array(
432  'type' => 'email',
433  'value' => '',
434  'required' => FALSE,
435  ),
436  'wwwroot' => array(
437  'type' => 'url',
438  'value' => _elgg_services()->config->getSiteUrl(),
439  'required' => TRUE,
440  ),
441  'dataroot' => array(
442  'type' => 'text',
443  'value' => '',
444  'required' => TRUE,
445  ),
446  'siteaccess' => array(
447  'type' => 'access',
448  'value' => ACCESS_PUBLIC,
449  'required' => TRUE,
450  ),
451  );
452 
453  // if Apache, we give user option of having Elgg create data directory
454  //if (ElggRewriteTester::guessWebServer() == 'apache') {
455  // $formVars['dataroot']['type'] = 'combo';
456  // $GLOBALS['_ELGG']->translations['en']['install:settings:help:dataroot'] =
457  // $GLOBALS['_ELGG']->translations['en']['install:settings:help:dataroot:apache'];
458  //}
459 
460  if ($this->isAction) {
461  do {
462  //if (!$this->createDataDirectory($submissionVars, $formVars)) {
463  // break;
464  //}
465 
466  if (!$this->validateSettingsVars($submissionVars, $formVars)) {
467  break;
468  }
469 
470  if (!$this->saveSiteSettings($submissionVars)) {
471  break;
472  }
473 
474  system_message(_elgg_services()->translator->translate('install:success:settings'));
475 
476  $this->continueToNextStep('settings');
477 
478  } while (FALSE); // PHP doesn't support breaking out of if statements
479  }
480 
481  $formVars = $this->makeFormSticky($formVars, $submissionVars);
482 
483  $this->render('settings', array('variables' => $formVars));
484  }
485 
495  protected function admin($submissionVars) {
496  $formVars = array(
497  'displayname' => array(
498  'type' => 'text',
499  'value' => '',
500  'required' => TRUE,
501  ),
502  'email' => array(
503  'type' => 'email',
504  'value' => '',
505  'required' => TRUE,
506  ),
507  'username' => array(
508  'type' => 'text',
509  'value' => '',
510  'required' => TRUE,
511  ),
512  'password1' => array(
513  'type' => 'password',
514  'value' => '',
515  'required' => TRUE,
516  'pattern' => '.{6,}',
517  ),
518  'password2' => array(
519  'type' => 'password',
520  'value' => '',
521  'required' => TRUE,
522  ),
523  );
524 
525  if ($this->isAction) {
526  do {
527  if (!$this->validateAdminVars($submissionVars, $formVars)) {
528  break;
529  }
530 
531  if (!$this->createAdminAccount($submissionVars, $this->autoLogin)) {
532  break;
533  }
534 
535  system_message(_elgg_services()->translator->translate('install:success:admin'));
536 
537  $this->continueToNextStep('admin');
538 
539  } while (FALSE); // PHP doesn't support breaking out of if statements
540  }
541 
542  // bit of a hack to get the password help to show right number of characters
543 
544  $lang = _elgg_services()->translator->getCurrentLanguage();
545  $GLOBALS['_ELGG']->translations[$lang]['install:admin:help:password1'] =
546  sprintf($GLOBALS['_ELGG']->translations[$lang]['install:admin:help:password1'],
547  $this->CONFIG->min_password_length);
548 
549  $formVars = $this->makeFormSticky($formVars, $submissionVars);
550 
551  $this->render('admin', array('variables' => $formVars));
552  }
553 
559  protected function complete() {
560 
561  $params = array();
562  if ($this->autoLogin) {
563  $params['destination'] = 'admin';
564  } else {
565  $params['destination'] = 'index.php';
566  }
567 
568  $this->render('complete', $params);
569  }
570 
580  protected function getSteps() {
581  return $this->steps;
582  }
583 
591  protected function continueToNextStep($currentStep) {
592  $this->isAction = FALSE;
593  forward($this->getNextStepUrl($currentStep));
594  }
595 
603  protected function getNextStep($currentStep) {
604  $index = 1 + array_search($currentStep, $this->steps);
605  if (isset($this->steps[$index])) {
606  return $this->steps[$index];
607  } else {
608  return null;
609  }
610  }
611 
619  protected function getNextStepUrl($currentStep) {
620  $nextStep = $this->getNextStep($currentStep);
621  return _elgg_services()->config->getSiteUrl() . "install.php?step=$nextStep";
622  }
623 
630  protected function setInstallStatus() {
631  if (!is_readable($this->getSettingsPath())) {
632  return;
633  }
634 
635  $this->loadSettingsFile();
636 
637  $this->status['config'] = TRUE;
638 
639  // must be able to connect to database to jump install steps
640  $dbSettingsPass = $this->checkDatabaseSettings(
641  $this->CONFIG->dbuser,
642  $this->CONFIG->dbpass,
643  $this->CONFIG->dbname,
644  $this->CONFIG->dbhost
645  );
646 
647  if ($dbSettingsPass == FALSE) {
648  return;
649  }
650 
651  if (!include_once(\Elgg\Application::elggDir()->getPath("engine/lib/database.php"))) {
652  throw new InstallationException(_elgg_services()->translator->translate('InstallationException:MissingLibrary', array('database.php')));
653  }
654 
655  // check that the config table has been created
656  $query = "show tables";
657  $result = _elgg_services()->db->getData($query);
658  if ($result) {
659  foreach ($result as $table) {
660  $table = (array) $table;
661  if (in_array("{$this->CONFIG->dbprefix}config", $table)) {
662  $this->status['database'] = TRUE;
663  }
664  }
665  if ($this->status['database'] == FALSE) {
666  return;
667  }
668  } else {
669  // no tables
670  return;
671  }
672 
673  // check that the config table has entries
674  $query = "SELECT COUNT(*) AS total FROM {$this->CONFIG->dbprefix}config";
675  $result = _elgg_services()->db->getData($query);
676  if ($result && $result[0]->total > 0) {
677  $this->status['settings'] = TRUE;
678  } else {
679  return;
680  }
681 
682  // check that the users entity table has an entry
683  $query = "SELECT COUNT(*) AS total FROM {$this->CONFIG->dbprefix}users_entity";
684  $result = _elgg_services()->db->getData($query);
685  if ($result && $result[0]->total > 0) {
686  $this->status['admin'] = TRUE;
687  } else {
688  return;
689  }
690  }
691 
700  protected function checkInstallCompletion($step) {
701  if ($step != 'complete') {
702  if (!in_array(FALSE, $this->status)) {
703  // install complete but someone is trying to view an install page
704  forward();
705  }
706  }
707  }
708 
717  protected function resumeInstall($step) {
718  // only do a resume from the first step
719  if ($step !== 'welcome') {
720  return;
721  }
722 
723  if ($this->status['database'] == FALSE) {
724  return;
725  }
726 
727  if ($this->status['settings'] == FALSE) {
728  forward("install.php?step=settings");
729  }
730 
731  if ($this->status['admin'] == FALSE) {
732  forward("install.php?step=admin");
733  }
734 
735  // everything appears to be set up
736  forward("install.php?step=complete");
737  }
738 
748  protected function bootstrapEngine() {
749  $config = new \Elgg\Config($this->CONFIG);
750  $services = new \Elgg\Di\ServiceProvider($config);
751  (new \Elgg\Application($services))->loadCore();
752  }
753 
763  protected function finishBootstraping($step) {
764 
765  $dbIndex = array_search('database', $this->getSteps());
766  $settingsIndex = array_search('settings', $this->getSteps());
767  $adminIndex = array_search('admin', $this->getSteps());
768  $completeIndex = array_search('complete', $this->getSteps());
769  $stepIndex = array_search($step, $this->getSteps());
770 
771  // To log in the user, we need to use the Elgg core session handling.
772  // Otherwise, use default php session handling
773  $useElggSession = ($stepIndex == $adminIndex && $this->isAction) ||
774  $stepIndex == $completeIndex;
775  if (!$useElggSession) {
776  session_name('Elgg_install');
777  session_start();
778  _elgg_services()->events->unregisterHandler('boot', 'system', 'session_init');
779  }
780 
781  if ($stepIndex > $dbIndex) {
782  // once the database has been created, load rest of engine
783 
784  $lib_dir = \Elgg\Application::elggDir()->chroot('/engine/lib/');
785 
786  $this->loadSettingsFile();
787 
788  $lib_files = array(
789  // these want to be loaded first apparently?
790  'autoloader.php',
791  'database.php',
792  'actions.php',
793 
794  'admin.php',
795  'annotations.php',
796  'cron.php',
797  'entities.php',
798  'extender.php',
799  'filestore.php',
800  'group.php',
801  'mb_wrapper.php',
802  'memcache.php',
803  'metadata.php',
804  'metastrings.php',
805  'navigation.php',
806  'notification.php',
807  'objects.php',
808  'pagehandler.php',
809  'pam.php',
810  'plugins.php',
811  'private_settings.php',
812  'relationships.php',
813  'river.php',
814  'sites.php',
815  'statistics.php',
816  'tags.php',
817  'user_settings.php',
818  'users.php',
819  'upgrade.php',
820  'widgets.php',
821  'deprecated-1.9.php',
822  );
823 
824  foreach ($lib_files as $file) {
825  if (!include_once($lib_dir->getPath($file))) {
826  throw new InstallationException('InstallationException:MissingLibrary', array($file));
827  }
828  }
829 
830  _elgg_services()->db->setupConnections();
831  _elgg_services()->translator->registerTranslations(\Elgg\Application::elggDir()->getPath("/languages/"));
832  $this->CONFIG->language = 'en';
833 
834  if ($stepIndex > $settingsIndex) {
835  $this->CONFIG->site_guid = (int) _elgg_services()->datalist->get('default_site');
836  $this->CONFIG->site_id = $this->CONFIG->site_guid;
837  $this->CONFIG->site = get_entity($this->CONFIG->site_guid);
838  $this->CONFIG->dataroot = _elgg_services()->datalist->get('dataroot');
839  _elgg_services()->config->getCookieConfig();
841  }
842 
843  _elgg_services()->events->trigger('init', 'system');
844  }
845  }
846 
852  protected function bootstrapConfig() {
853  $this->CONFIG->installer_running = true;
854 
855  $this->CONFIG->wwwroot = $this->getBaseUrl();
856  $this->CONFIG->url = $this->CONFIG->wwwroot;
857  $this->CONFIG->path = \Elgg\Application::elggDir()->getPath() . "/";
858  $GLOBALS['_ELGG']->view_path = $this->CONFIG->path . 'views/';
859  $this->CONFIG->pluginspath = $this->CONFIG->path . 'mod/';
860  $this->CONFIG->context = array();
861  $this->CONFIG->entity_types = array('group', 'object', 'site', 'user');
862 
863  // required by elgg_view_page()
864  $this->CONFIG->sitename = '';
865  $this->CONFIG->sitedescription = '';
866 
867  // required by Elgg\Config::get
868  $this->CONFIG->site_guid = 1;
869  }
870 
874  private function isHttps() {
875  return (!empty($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") ||
876  (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443);
877  }
878 
887  protected function getBaseUrl() {
888  $protocol = $this->isHttps() ? 'https' : 'http';
889 
890  if (isset($_SERVER["SERVER_PORT"])) {
891  $port = ':' . $_SERVER["SERVER_PORT"];
892  } else {
893  $port = '';
894  }
895  if ($port == ':80' || $port == ':443') {
896  $port = '';
897  }
898  $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
899  $cutoff = strpos($uri, 'install.php');
900  $uri = substr($uri, 0, $cutoff);
901  $serverName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : '';
902 
903  return "$protocol://{$serverName}$port{$uri}";
904  }
905 
912  protected function loadSettingsFile() {
913  if (!include_once($this->getSettingsPath())) {
914  throw new InstallationException(_elgg_services()->translator->translate('InstallationException:CannotLoadSettings'));
915  }
916  }
917 
931  protected function getPostVariables() {
932  $vars = array();
933  foreach ($_POST as $k => $v) {
934  $vars[$k] = $v;
935  }
936  return $vars;
937  }
938 
947  protected function makeFormSticky($formVars, $submissionVars) {
948  foreach ($submissionVars as $field => $value) {
949  $formVars[$field]['value'] = $value;
950  }
951  return $formVars;
952  }
953 
965  protected function isInstallDirWritable(&$report) {
966  $root = Directory\Local::root()->getPath();
967  $abs_path = \Elgg\Application::elggDir()->getPath('elgg-config');
968 
969  if (0 === strpos($abs_path, $root)) {
970  $relative_path = substr($abs_path, strlen($root));
971  } else {
972  $relative_path = $abs_path;
973  }
974  $relative_path = rtrim($relative_path, '/\\');
975 
976  $writable = is_writable(Directory\Local::root()->getPath('elgg-config'));
977  if (!$writable) {
978  $report['settings'] = array(
979  array(
980  'severity' => 'failure',
981  'message' => _elgg_services()->translator->translate('install:check:installdir', [$relative_path]),
982  )
983  );
984  return FALSE;
985  }
986 
987  return TRUE;
988  }
989 
997  protected function checkSettingsFile(&$report = array()) {
998 
999 
1000  if (!file_exists($this->getSettingsPath())) {
1001  return FALSE;
1002  }
1003 
1004  if (!is_readable($this->getSettingsPath())) {
1005  $report['settings'] = array(
1006  array(
1007  'severity' => 'failure',
1008  'message' => _elgg_services()->translator->translate('install:check:readsettings'),
1009  )
1010  );
1011  }
1012 
1013  return TRUE;
1014  }
1015 
1021  private function getSettingsPath() {
1022  return Directory\Local::root()->getPath("elgg-config/settings.php");
1023  }
1024 
1032  protected function checkPHP(&$report) {
1033  $phpReport = array();
1034 
1035  $min_php_version = '5.5.0';
1036  if (version_compare(PHP_VERSION, $min_php_version, '<')) {
1037  $phpReport[] = array(
1038  'severity' => 'failure',
1039  'message' => _elgg_services()->translator->translate('install:check:php:version', array($min_php_version, PHP_VERSION))
1040  );
1041  }
1042 
1043  $this->checkPhpExtensions($phpReport);
1044 
1045  $this->checkPhpDirectives($phpReport);
1046 
1047  if (count($phpReport) == 0) {
1048  $phpReport[] = array(
1049  'severity' => 'pass',
1050  'message' => _elgg_services()->translator->translate('install:check:php:success')
1051  );
1052  }
1053 
1054  $report['php'] = $phpReport;
1055  }
1056 
1064  protected function checkPhpExtensions(&$phpReport) {
1065  $extensions = get_loaded_extensions();
1066  $requiredExtensions = array(
1067  'pdo_mysql',
1068  'json',
1069  'xml',
1070  'gd',
1071  );
1072  foreach ($requiredExtensions as $extension) {
1073  if (!in_array($extension, $extensions)) {
1074  $phpReport[] = array(
1075  'severity' => 'failure',
1076  'message' => _elgg_services()->translator->translate('install:check:php:extension', array($extension))
1077  );
1078  }
1079  }
1080 
1081  $recommendedExtensions = array(
1082  'mbstring',
1083  );
1084  foreach ($recommendedExtensions as $extension) {
1085  if (!in_array($extension, $extensions)) {
1086  $phpReport[] = array(
1087  'severity' => 'warning',
1088  'message' => _elgg_services()->translator->translate('install:check:php:extension:recommend', array($extension))
1089  );
1090  }
1091  }
1092  }
1093 
1101  protected function checkPhpDirectives(&$phpReport) {
1102  if (ini_get('open_basedir')) {
1103  $phpReport[] = array(
1104  'severity' => 'warning',
1105  'message' => _elgg_services()->translator->translate("install:check:php:open_basedir")
1106  );
1107  }
1108 
1109  if (ini_get('safe_mode')) {
1110  $phpReport[] = array(
1111  'severity' => 'warning',
1112  'message' => _elgg_services()->translator->translate("install:check:php:safe_mode")
1113  );
1114  }
1115 
1116  if (ini_get('arg_separator.output') !== '&') {
1117  $separator = htmlspecialchars(ini_get('arg_separator.output'));
1118  $msg = _elgg_services()->translator->translate("install:check:php:arg_separator", array($separator));
1119  $phpReport[] = array(
1120  'severity' => 'failure',
1121  'message' => $msg,
1122  );
1123  }
1124 
1125  if (ini_get('register_globals')) {
1126  $phpReport[] = array(
1127  'severity' => 'failure',
1128  'message' => _elgg_services()->translator->translate("install:check:php:register_globals")
1129  );
1130  }
1131 
1132  if (ini_get('session.auto_start')) {
1133  $phpReport[] = array(
1134  'severity' => 'failure',
1135  'message' => _elgg_services()->translator->translate("install:check:php:session.auto_start")
1136  );
1137  }
1138  }
1139 
1147  protected function checkRewriteRules(&$report) {
1148 
1149 
1150  $tester = new ElggRewriteTester();
1151  $url = _elgg_services()->config->getSiteUrl() . "rewrite.php";
1152  $report['rewrite'] = array($tester->run($url, Directory\Local::root()->getPath()));
1153  }
1154 
1161  protected function processRewriteTest() {
1162  if (strpos($_SERVER['REQUEST_URI'], 'rewrite.php') !== FALSE) {
1163  echo \Elgg\Application::REWRITE_TEST_OUTPUT;
1164  exit;
1165  }
1166  }
1167 
1176  protected function countNumConditions($report, $condition) {
1177  $count = 0;
1178  foreach ($report as $category => $checks) {
1179  foreach ($checks as $check) {
1180  if ($check['severity'] === $condition) {
1181  $count++;
1182  }
1183  }
1184  }
1185 
1186  return $count;
1187  }
1188 
1189 
1202  protected function validateDatabaseVars($submissionVars, $formVars) {
1203 
1204  foreach ($formVars as $field => $info) {
1205  if ($info['required'] == TRUE && !$submissionVars[$field]) {
1206  $name = _elgg_services()->translator->translate("install:database:label:$field");
1207  register_error(_elgg_services()->translator->translate('install:error:requiredfield', array($name)));
1208  return FALSE;
1209  }
1210  }
1211 
1212  // according to postgres documentation: SQL identifiers and key words must
1213  // begin with a letter (a-z, but also letters with diacritical marks and
1214  // non-Latin letters) or an underscore (_). Subsequent characters in an
1215  // identifier or key word can be letters, underscores, digits (0-9), or dollar signs ($).
1216  // Refs #4994
1217  if (!preg_match("/^[a-zA-Z_][\w]*$/", $submissionVars['dbprefix'])) {
1218  register_error(_elgg_services()->translator->translate('install:error:database_prefix'));
1219  return FALSE;
1220  }
1221 
1222  return $this->checkDatabaseSettings(
1223  $submissionVars['dbuser'],
1224  $submissionVars['dbpassword'],
1225  $submissionVars['dbname'],
1226  $submissionVars['dbhost']
1227  );
1228  }
1229 
1240  protected function checkDatabaseSettings($user, $password, $dbname, $host) {
1241  $config = new \Elgg\Database\Config((object)[
1242  'dbhost' => $host,
1243  'dbuser' => $user,
1244  'dbpass' => $password,
1245  'dbname' => $dbname,
1246  ]);
1247  $db = new \Elgg\Database($config);
1248 
1249  try {
1250  $db->getDataRow("SELECT 1");
1251  } catch (DatabaseException $e) {
1252  if (0 === strpos($e->getMessage(), "Elgg couldn't connect")) {
1253  register_error(_elgg_services()->translator->translate('install:error:databasesettings'));
1254  } else {
1255  register_error(_elgg_services()->translator->translate('install:error:nodatabase', array($dbname)));
1256  }
1257  return FALSE;
1258  }
1259 
1260  // check MySQL version - must be 5.0 or >
1261  $version = $db->getServerVersion(\Elgg\Database\Config::READ_WRITE);
1262  $required_version = 5.0;
1263  $points = explode('.', $version);
1264  if ($points[0] < $required_version) {
1265  register_error(_elgg_services()->translator->translate('install:error:oldmysql', array($version)));
1266  return FALSE;
1267  }
1268 
1269  return TRUE;
1270  }
1271 
1279  protected function createSettingsFile($params) {
1280  $template = \Elgg\Application::elggDir()->getContents("elgg-config/settings.example.php");
1281  if (!$template) {
1282  register_error(_elgg_services()->translator->translate('install:error:readsettingsphp'));
1283  return FALSE;
1284  }
1285 
1286  foreach ($params as $k => $v) {
1287  $template = str_replace("{{" . $k . "}}", $v, $template);
1288  }
1289 
1290  $result = file_put_contents($this->getSettingsPath(), $template);
1291  if (!$result) {
1292  register_error(_elgg_services()->translator->translate('install:error:writesettingphp'));
1293  return FALSE;
1294  }
1295 
1296  return TRUE;
1297  }
1298 
1304  protected function connectToDatabase() {
1305 
1306 
1307  if (!include_once($this->getSettingsPath())) {
1308  register_error('Elgg could not load the settings file. It does not exist or there is a file permissions issue.');
1309  return FALSE;
1310  }
1311 
1312  if (!include_once(\Elgg\Application::elggDir()->getPath("engine/lib/database.php"))) {
1313  register_error('Could not load database.php');
1314  return FALSE;
1315  }
1316 
1317  try {
1318  _elgg_services()->db->setupConnections();
1319  } catch (DatabaseException $e) {
1320  register_error($e->getMessage());
1321  return FALSE;
1322  }
1323 
1324  return TRUE;
1325  }
1326 
1332  protected function installDatabase() {
1333 
1334 
1335  try {
1336  _elgg_services()->db->runSqlScript(\Elgg\Application::elggDir()->getPath("/engine/schema/mysql.sql"));
1337  } catch (Exception $e) {
1338  $msg = $e->getMessage();
1339  if (strpos($msg, 'already exists')) {
1340  $msg = _elgg_services()->translator->translate('install:error:tables_exist');
1341  }
1342  register_error($msg);
1343  return FALSE;
1344  }
1345 
1346  return TRUE;
1347  }
1348 
1361  protected function createDataDirectory(&$submissionVars, $formVars) {
1362  // did the user have option of Elgg creating the data directory
1363  if ($formVars['dataroot']['type'] != 'combo') {
1364  return TRUE;
1365  }
1366 
1367  // did the user select the option
1368  if ($submissionVars['dataroot'] != 'dataroot-checkbox') {
1369  return TRUE;
1370  }
1371 
1372  $dir = sanitise_filepath($submissionVars['path']) . 'data';
1373  if (file_exists($dir) || mkdir($dir, 0700)) {
1374  $submissionVars['dataroot'] = $dir;
1375  if (!file_exists("$dir/.htaccess")) {
1376  $htaccess = "Order Deny,Allow\nDeny from All\n";
1377  if (!file_put_contents("$dir/.htaccess", $htaccess)) {
1378  return FALSE;
1379  }
1380  }
1381  return TRUE;
1382  }
1383 
1384  return FALSE;
1385  }
1386 
1395  protected function validateSettingsVars($submissionVars, $formVars) {
1396 
1397 
1398  foreach ($formVars as $field => $info) {
1399  $submissionVars[$field] = trim($submissionVars[$field]);
1400  if ($info['required'] == TRUE && $submissionVars[$field] === '') {
1401  $name = _elgg_services()->translator->translate("install:settings:label:$field");
1402  register_error(_elgg_services()->translator->translate('install:error:requiredfield', array($name)));
1403  return FALSE;
1404  }
1405  }
1406 
1407  // check that data root is absolute path
1408  if (stripos(PHP_OS, 'win') === 0) {
1409  if (strpos($submissionVars['dataroot'], ':') !== 1) {
1410  $msg = _elgg_services()->translator->translate('install:error:relative_path', array($submissionVars['dataroot']));
1411  register_error($msg);
1412  return FALSE;
1413  }
1414  } else {
1415  if (strpos($submissionVars['dataroot'], '/') !== 0) {
1416  $msg = _elgg_services()->translator->translate('install:error:relative_path', array($submissionVars['dataroot']));
1417  register_error($msg);
1418  return FALSE;
1419  }
1420  }
1421 
1422  // check that data root exists
1423  if (!file_exists($submissionVars['dataroot'])) {
1424  $msg = _elgg_services()->translator->translate('install:error:datadirectoryexists', array($submissionVars['dataroot']));
1425  register_error($msg);
1426  return FALSE;
1427  }
1428 
1429  // check that data root is writable
1430  if (!is_writable($submissionVars['dataroot'])) {
1431  $msg = _elgg_services()->translator->translate('install:error:writedatadirectory', array($submissionVars['dataroot']));
1432  register_error($msg);
1433  return FALSE;
1434  }
1435 
1436  if (!isset($this->CONFIG->data_dir_override) || !$this->CONFIG->data_dir_override) {
1437  // check that data root is not subdirectory of Elgg root
1438  if (stripos($submissionVars['dataroot'], $submissionVars['path']) === 0) {
1439  $msg = _elgg_services()->translator->translate('install:error:locationdatadirectory', array($submissionVars['dataroot']));
1440  register_error($msg);
1441  return FALSE;
1442  }
1443  }
1444 
1445  // check that email address is email address
1446  if ($submissionVars['siteemail'] && !is_email_address($submissionVars['siteemail'])) {
1447  $msg = _elgg_services()->translator->translate('install:error:emailaddress', array($submissionVars['siteemail']));
1448  register_error($msg);
1449  return FALSE;
1450  }
1451 
1452  // @todo check that url is a url
1453  // @note filter_var cannot be used because it doesn't work on international urls
1454 
1455  return TRUE;
1456  }
1457 
1465  protected function saveSiteSettings($submissionVars) {
1466 
1467 
1468  // ensure that file path, data path, and www root end in /
1469  $submissionVars['dataroot'] = sanitise_filepath($submissionVars['dataroot']);
1470  $submissionVars['wwwroot'] = sanitise_filepath($submissionVars['wwwroot']);
1471 
1472  $site = new ElggSite();
1473  $site->name = strip_tags($submissionVars['sitename']);
1474  $site->url = $submissionVars['wwwroot'];
1475  $site->access_id = ACCESS_PUBLIC;
1476  $site->email = $submissionVars['siteemail'];
1477  $guid = $site->save();
1478 
1479  if (!$guid) {
1480  register_error(_elgg_services()->translator->translate('install:error:createsite'));
1481  return FALSE;
1482  }
1483 
1484  // bootstrap site info
1485  $this->CONFIG->site_guid = $guid;
1486  $this->CONFIG->site_id = $guid;
1487  $this->CONFIG->site = $site;
1488 
1489  _elgg_services()->datalist->set('installed', time());
1490  _elgg_services()->datalist->set('dataroot', $submissionVars['dataroot']);
1491  _elgg_services()->datalist->set('default_site', $site->getGUID());
1492  _elgg_services()->datalist->set('version', elgg_get_version());
1493  _elgg_services()->datalist->set('simplecache_enabled', 1);
1494  _elgg_services()->datalist->set('system_cache_enabled', 1);
1495  _elgg_services()->datalist->set('simplecache_lastupdate', time());
1496 
1497  // new installations have run all the upgrades
1498  $upgrades = elgg_get_upgrade_files(\Elgg\Application::elggDir()->getPath("/engine/lib/upgrades/"));
1499  _elgg_services()->datalist->set('processed_upgrades', serialize($upgrades));
1500 
1501  _elgg_services()->configTable->set('view', 'default', $site->getGUID());
1502  _elgg_services()->configTable->set('language', 'en', $site->getGUID());
1503  _elgg_services()->configTable->set('default_access', $submissionVars['siteaccess'], $site->getGUID());
1504  _elgg_services()->configTable->set('allow_registration', TRUE, $site->getGUID());
1505  _elgg_services()->configTable->set('walled_garden', FALSE, $site->getGUID());
1506  _elgg_services()->configTable->set('allow_user_default_access', '', $site->getGUID());
1507  _elgg_services()->configTable->set('default_limit', 10, $site->getGUID());
1508 
1509  $this->setSubtypeClasses();
1510 
1511  $this->enablePlugins();
1512 
1513  return TRUE;
1514  }
1515 
1521  protected function setSubtypeClasses() {
1522  add_subtype("object", "plugin", "ElggPlugin");
1523  add_subtype("object", "file", "ElggFile");
1524  add_subtype("object", "widget", "ElggWidget");
1525  add_subtype("object", "comment", "ElggComment");
1526  add_subtype("object", "elgg_upgrade", 'ElggUpgrade');
1527  }
1528 
1534  protected function enablePlugins() {
1536  $plugins = elgg_get_plugins('any');
1537  foreach ($plugins as $plugin) {
1538  if ($plugin->getManifest()) {
1539  if ($plugin->getManifest()->getActivateOnInstall()) {
1540  $plugin->activate();
1541  }
1542  if (in_array('theme', $plugin->getManifest()->getCategories())) {
1543  $plugin->setPriority('last');
1544  }
1545  }
1546  }
1547  }
1548 
1561  protected function validateAdminVars($submissionVars, $formVars) {
1562 
1563  foreach ($formVars as $field => $info) {
1564  if ($info['required'] == TRUE && !$submissionVars[$field]) {
1565  $name = _elgg_services()->translator->translate("install:admin:label:$field");
1566  register_error(_elgg_services()->translator->translate('install:error:requiredfield', array($name)));
1567  return FALSE;
1568  }
1569  }
1570 
1571  if ($submissionVars['password1'] !== $submissionVars['password2']) {
1572  register_error(_elgg_services()->translator->translate('install:admin:password:mismatch'));
1573  return FALSE;
1574  }
1575 
1576  if (trim($submissionVars['password1']) == "") {
1577  register_error(_elgg_services()->translator->translate('install:admin:password:empty'));
1578  return FALSE;
1579  }
1580 
1581  $minLength = _elgg_services()->configTable->get('min_password_length');
1582  if (strlen($submissionVars['password1']) < $minLength) {
1583  register_error(_elgg_services()->translator->translate('install:admin:password:tooshort'));
1584  return FALSE;
1585  }
1586 
1587  // check that email address is email address
1588  if ($submissionVars['email'] && !is_email_address($submissionVars['email'])) {
1589  $msg = _elgg_services()->translator->translate('install:error:emailaddress', array($submissionVars['email']));
1590  register_error($msg);
1591  return FALSE;
1592  }
1593 
1594  return TRUE;
1595  }
1596 
1605  protected function createAdminAccount($submissionVars, $login = FALSE) {
1606  try {
1607  $guid = register_user(
1608  $submissionVars['username'],
1609  $submissionVars['password1'],
1610  $submissionVars['displayname'],
1611  $submissionVars['email']
1612  );
1613  } catch (Exception $e) {
1614  register_error($e->getMessage());
1615  return false;
1616  }
1617 
1618  if (!$guid) {
1619  register_error(_elgg_services()->translator->translate('install:admin:cannot_create'));
1620  return false;
1621  }
1622 
1623  $user = get_entity($guid);
1624  if (!$user instanceof ElggUser) {
1625  register_error(_elgg_services()->translator->translate('install:error:loadadmin'));
1626  return false;
1627  }
1628 
1629  elgg_set_ignore_access(TRUE);
1630  if ($user->makeAdmin() == FALSE) {
1631  register_error(_elgg_services()->translator->translate('install:error:adminaccess'));
1632  } else {
1633  _elgg_services()->datalist->set('admin_registered', 1);
1634  }
1635  elgg_set_ignore_access(false);
1636 
1637  // add validation data to satisfy user validation plugins
1638  create_metadata($guid, 'validated', TRUE, '', 0, ACCESS_PUBLIC);
1639  create_metadata($guid, 'validated_method', 'admin_user', '', 0, ACCESS_PUBLIC);
1640 
1641  if ($login) {
1643 
1644  // session.cache_limiter is unfortunately set to "" by the NativeSessionStorage constructor,
1645  // so we must capture and inject it directly.
1646  $options = [
1647  'cache_limiter' => session_cache_limiter(),
1648  ];
1650 
1651  $session = new ElggSession(new Symfony\Component\HttpFoundation\Session\Session($storage));
1652  $session->setName('Elgg');
1653  _elgg_services()->setValue('session', $session);
1654  if (login($user) == FALSE) {
1655  register_error(_elgg_services()->translator->translate('install:error:adminlogin'));
1656  }
1657  }
1658 
1659  return TRUE;
1660  }
1661 }
checkSettingsFile(&$report=array())
Check that the settings file exists.
A simple directory abstraction.
Definition: Directory.php:13
$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.
$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
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
$extensions
sanitise_filepath($path, $append_slash=true)
Sanitise file paths ensuring that they begin and end with slashes etc.
Definition: elgglib.php:399
$_ELGG translations
String translations for the current language.
Definition: config.php:321
$value
Definition: longtext.php:26
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
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
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:26
elgg_set_viewtype($viewtype="")
Manually set the viewtype.
Definition: views.php:73
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:342
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:1990
elgg subtext time
elgg_get_version($human_readable=false)
Get the current Elgg version information.
Definition: elgglib.php:1043
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.
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:408
$session
Definition: login.php:9
database($submissionVars)
Database set up controller.
$version
Definition: version.php:14
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:437
validateAdminVars($submissionVars, $formVars)
Admin account support methods.