Elgg  Version master
Config.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg;
4 
7 use Elgg\Traits\Loggable;
8 
132 class Config {
133 
134  use Loggable;
135 
136  private array $values = [];
137 
138  private array $initial_values = [];
139 
140  private bool $cookies_configured = false;
141 
142  private array $cookies = [];
143 
147  protected array $locked_values = [
148  'assetroot',
149  'cacheroot',
150  'dataroot',
151  'installed',
152  'plugins_path',
153  'wwwroot',
154  ];
155 
159  protected array $deprecated = [];
160 
164  protected array $config_defaults = [
165  'admin_validation_notification' => false,
166  'allow_phpinfo' => false,
167  'authentication_failures_lifetime' => 600,
168  'authentication_failures_limit' => 5,
169  'auto_disable_plugins' => true,
170  'batch_run_time_in_secs' => 4,
171  'boot_cache_ttl' => 3600,
172  'can_change_username' => false,
173  'class_loader_verify_file_existence' => true,
174  'comment_box_collapses' => true,
175  'comments_group_only' => true,
176  'comments_latest_first' => true,
177  'comments_max_depth' => 0,
178  'comments_per_page' => 25,
179  'db_enable_query_logging' => false,
180  'db_query_cache_limit' => 50,
181  'default_limit' => 10,
182  'elgg_maintenance_mode' => false,
183  'email_html_part' => true,
184  'email_html_part_images' => 'no',
185  'email_subject_limit' => 998,
186  'emailer_transport' => PHP_OS_FAMILY === 'Windows' ? 'native://default' : 'sendmail://default',
187  'enable_delayed_email' => true,
188  'friendly_time_number_of_days' => 30,
189  'icon_sizes' => [
190  'topbar' => ['w' => 16, 'h' => 16, 'square' => true, 'upscale' => true],
191  'tiny' => ['w' => 25, 'h' => 25, 'square' => true, 'upscale' => true],
192  'small' => ['w' => 40, 'h' => 40, 'square' => true, 'upscale' => true],
193  'medium' => ['w' => 100, 'h' => 100, 'square' => true, 'upscale' => true],
194  'large' => ['w' => 200, 'h' => 200, 'square' => true, 'upscale' => true],
195  'master' => ['w' => 10240, 'h' => 10240, 'square' => false, 'upscale' => false, 'crop' => false],
196  ],
197  'language' => 'en',
198  'language_detect_from_browser' => true,
199  'lastcache' => 0,
200  'mentions_display_format' => 'display_name',
201  'message_delay' => 6,
202  'min_password_length' => 6,
203  'minusername' => 4,
204  'notifications_max_runtime' => 45,
205  'notifications_queue_delay' => 0,
206  'pagination_behaviour' => 'ajax-replace',
207  'require_admin_validation' => false,
208  'security_email_require_confirmation' => true,
209  'security_email_require_password' => true,
210  'security_notify_admins' => true,
211  'security_notify_user_password' => true,
212  'security_protect_upgrade' => true,
213  'session_bound_entity_icons' => false,
214  'simplecache_enabled' => false,
215  'subresource_integrity_enabled' => false,
216  'system_cache_enabled' => false,
217  'testing_mode' => false,
218  'trash_enabled' => true,
219  'trash_retention' => 30,
220  'user_joined_river' => false,
221  'webp_enabled' => true,
222  'who_can_change_language' => 'everyone',
223  ];
224 
228  protected array $path_properties = [
229  'assetroot',
230  'cacheroot',
231  'dataroot',
232  'plugins_path',
233  ];
234 
240  const ENTITY_TYPES = ['group', 'object', 'site', 'user'];
241 
247  const SENSITIVE_PROPERTIES = [
248  '__site_secret__',
249  'db',
250  'dbhost',
251  'dbport',
252  'dbuser',
253  'dbpass',
254  'dbname',
255  ];
256 
262  public function __construct(array $values = []) {
263  $this->saveInitialValues($values);
264 
265  $this->values = array_merge($this->config_defaults, $values);
266 
267  // set cookie values for session and remember me
268  $this->getCookieConfig();
269  }
270 
278  protected function saveInitialValues(array $values): void {
279  // Don't keep copies of these in case config gets dumped
280  foreach (self::SENSITIVE_PROPERTIES as $name) {
281  unset($values[$name]);
282  }
283 
284  $this->initial_values = $values;
285  }
286 
294  public static function factory(string $settings_path = ''): static {
295  $settings_path = self::resolvePath($settings_path);
296 
297  return self::fromFile($settings_path);
298  }
299 
308  protected static function fromFile($path): static {
309  if (!is_file($path)) {
310  throw new ConfigurationException(__METHOD__ . ": Reading configs failed: File {$path} not present.");
311  }
312 
313  if (!is_readable($path)) {
314  throw new ConfigurationException(__METHOD__ . ": Reading configs failed: File {$path} not readable.");
315  }
316 
317  // legacy loading. If $CONFIG doesn't exist, remove it after the
318  // settings file is read.
319  if (isset($GLOBALS['CONFIG'])) {
320  // don't overwrite it
321  $global = $GLOBALS['CONFIG'];
322  unset($GLOBALS['CONFIG']);
323  } else {
324  $global = null;
325  }
326 
327  Includer::requireFile($path);
328 
329  if (empty($GLOBALS['CONFIG']->dataroot)) {
330  throw new ConfigurationException(__METHOD__ . ': Reading configs failed: The Elgg settings file is missing $CONFIG->dataroot.');
331  }
332 
333  if (empty($GLOBALS['CONFIG']->wwwroot)) {
334  throw new ConfigurationException(__METHOD__ . ': Reading configs failed: The Elgg settings file is missing $CONFIG->wwwroot.');
335  }
336 
337  $config = new self(get_object_vars($GLOBALS['CONFIG']));
338 
339  if ($global !== null) {
340  // restore
341  $GLOBALS['CONFIG'] = $global;
342  } else {
343  unset($GLOBALS['CONFIG']);
344  }
345 
346  if ($config->{'X-Sendfile-Type'}) {
347  $config->{'x_sendfile_type'} = $config->{'X-Sendfile-Type'};
348  unset($config->{'X-Sendfile-Type'});
349  }
350 
351  if ($config->{'X-Accel-Mapping'}) {
352  $config->{'x_accel_mapping'} = $config->{'X-Accel-Mapping'};
353  unset($config->{'X-Accel-Mapping'});
354  }
355 
356  return $config;
357  }
358 
366  public static function resolvePath(string $settings_path = ''): string {
367  if (empty($settings_path)) {
368  $settings_path = Paths::settingsFile(Paths::SETTINGS_PHP);
369  }
370 
371  return Paths::sanitize($settings_path, false);
372  }
373 
379  public function getValues(): array {
380  return $this->values;
381  }
382 
388  public function getCookieConfig(): array {
389  if ($this->cookies_configured) {
390  return $this->cookies;
391  }
392 
393  $cookies = [];
394  if ($this->hasInitialValue('cookies')) {
395  $cookies = $this->getInitialValue('cookies');
396  }
397 
398  // session cookie config
399  if (!isset($cookies['session'])) {
400  $cookies['session'] = [];
401  }
402 
403  $session_defaults = session_get_cookie_params();
404  $session_defaults['name'] = 'Elgg';
405  $cookies['session'] = array_merge($session_defaults, $cookies['session']);
406 
407  // remember me cookie config
408  if (!isset($cookies['remember_me'])) {
409  $cookies['remember_me'] = [];
410  }
411 
412  $session_defaults['name'] = 'elggperm';
413  $session_defaults['expire'] = strtotime('+30 days');
414  $cookies['remember_me'] = array_merge($session_defaults, $cookies['remember_me']);
415 
416  $this->cookies = $cookies;
417  $this->cookies_configured = true;
418 
419  return $cookies;
420  }
421 
431  public function __get(string $name) {
432 
433  if (array_key_exists($name, $this->deprecated)) {
434  elgg_deprecated_notice("Using '{$name}' from config has been deprecated", $this->deprecated[$name]);
435  }
436 
437  if (!isset($this->values[$name])) {
438  return null;
439  }
440 
441  $value = $this->values[$name];
442  if (in_array($name, $this->path_properties)) {
443  $value = Paths::sanitize($value);
444  }
445 
446  return $value;
447  }
448 
456  public function hasValue(string $name): bool {
457  return isset($this->values[$name]);
458  }
459 
466  public function getInitialValue(string $name) {
467  return $this->initial_values[$name] ?? null;
468  }
469 
477  public function hasInitialValue(string $name): bool {
478  return isset($this->initial_values[$name]);
479  }
480 
488  public function isLocked(string $name): bool {
489  $testing = $this->values['testing_mode'] ?? false;
490  return !$testing && in_array($name, $this->locked_values) && $this->hasValue($name);
491  }
492 
502  public function __set(string $name, $value): void {
503  if ($this->wasWarnedLocked($name)) {
504  return;
505  }
506 
507  if (in_array($name, $this->path_properties)) {
508  $value = Paths::sanitize($value);
509  }
510 
511  $this->values[$name] = $value;
512  }
513 
520  public function __isset(string $name): bool {
521  return $this->__get($name) !== null;
522  }
523 
530  public function __unset(string $name): void {
531  if ($this->wasWarnedLocked($name)) {
532  return;
533  }
534 
535  unset($this->values[$name]);
536  }
537 
546  public function save(string $name, $value): bool {
547  if ($this->wasWarnedLocked($name)) {
548  return false;
549  }
550 
551  if (strlen($name) > 255) {
552  $this->getLogger()->error('The name length for configuration variables cannot be greater than 255');
553  return false;
554  }
555 
556  if ($value === null) {
557  // don't save null values
558  return $this->remove($name);
559  }
560 
561  $result = _elgg_services()->configTable->set($name, $value);
562 
563  $this->__set($name, $value);
564 
565  return $result;
566  }
567 
575  public function remove(string $name): bool {
576  if ($this->wasWarnedLocked($name)) {
577  return false;
578  }
579 
580  $result = _elgg_services()->configTable->remove($name);
581 
582  unset($this->values[$name]);
583 
584  return $result;
585  }
586 
593  protected function wasWarnedLocked(string $name): bool {
594  if (!$this->isLocked($name)) {
595  return false;
596  }
597 
598  $this->getLogger()->warning("The property {$name} is read-only.");
599 
600  return true;
601  }
602 }
if(! $user||! $user->canDelete()) $name
Definition: delete.php:22
return[ 'admin/delete_admin_notices'=>['access'=> 'admin'], 'admin/menu/save'=>['access'=> 'admin'], 'admin/plugins/activate'=>['access'=> 'admin'], 'admin/plugins/activate_all'=>['access'=> 'admin'], 'admin/plugins/deactivate'=>['access'=> 'admin'], 'admin/plugins/deactivate_all'=>['access'=> 'admin'], 'admin/plugins/set_priority'=>['access'=> 'admin'], 'admin/security/security_txt'=>['access'=> 'admin'], 'admin/security/settings'=>['access'=> 'admin'], 'admin/security/regenerate_site_secret'=>['access'=> 'admin'], 'admin/site/cache/invalidate'=>['access'=> 'admin'], 'admin/site/flush_cache'=>['access'=> 'admin'], 'admin/site/icons'=>['access'=> 'admin'], 'admin/site/set_maintenance_mode'=>['access'=> 'admin'], 'admin/site/set_robots'=>['access'=> 'admin'], 'admin/site/theme'=>['access'=> 'admin'], 'admin/site/unlock_upgrade'=>['access'=> 'admin'], 'admin/site/settings'=>['access'=> 'admin'], 'admin/upgrade'=>['access'=> 'admin'], 'admin/upgrade/reset'=>['access'=> 'admin'], 'admin/user/ban'=>['access'=> 'admin'], 'admin/user/bulk/ban'=>['access'=> 'admin'], 'admin/user/bulk/delete'=>['access'=> 'admin'], 'admin/user/bulk/unban'=>['access'=> 'admin'], 'admin/user/bulk/validate'=>['access'=> 'admin'], 'admin/user/change_email'=>['access'=> 'admin'], 'admin/user/delete'=>['access'=> 'admin'], 'admin/user/login_as'=>['access'=> 'admin'], 'admin/user/logout_as'=>[], 'admin/user/makeadmin'=>['access'=> 'admin'], 'admin/user/resetpassword'=>['access'=> 'admin'], 'admin/user/removeadmin'=>['access'=> 'admin'], 'admin/user/unban'=>['access'=> 'admin'], 'admin/user/validate'=>['access'=> 'admin'], 'annotation/delete'=>[], 'avatar/upload'=>[], 'comment/save'=>[], 'diagnostics/download'=>['access'=> 'admin'], 'entity/chooserestoredestination'=>[], 'entity/delete'=>[], 'entity/mute'=>[], 'entity/restore'=>[], 'entity/subscribe'=>[], 'entity/trash'=>[], 'entity/unmute'=>[], 'entity/unsubscribe'=>[], 'login'=>['access'=> 'logged_out'], 'logout'=>[], 'notifications/mute'=>['access'=> 'public'], 'plugins/settings/remove'=>['access'=> 'admin'], 'plugins/settings/save'=>['access'=> 'admin'], 'plugins/usersettings/save'=>[], 'register'=>['access'=> 'logged_out', 'middleware'=>[\Elgg\Router\Middleware\RegistrationAllowedGatekeeper::class,],], 'river/delete'=>[], 'settings/notifications'=>[], 'settings/notifications/subscriptions'=>[], 'user/changepassword'=>['access'=> 'public'], 'user/requestnewpassword'=>['access'=> 'public'], 'useradd'=>['access'=> 'admin'], 'usersettings/save'=>[], 'widgets/add'=>[], 'widgets/delete'=>[], 'widgets/move'=>[], 'widgets/save'=>[],]
Definition: actions.php:73
foreach( $paths as $path)
Definition: autoloader.php:12
hasValue(string $name)
Test if we have a set value.
Definition: Config.php:456
isLocked(string $name)
Is this value locked?
Definition: Config.php:488
static fromFile($path)
Build a config from a file.
Definition: Config.php:308
__construct(array $values=[])
Constructor.
Definition: Config.php:262
getCookieConfig()
Set up and return the cookie configuration array resolved from settings.
Definition: Config.php:388
save(string $name, $value)
Save a configuration setting to the database.
Definition: Config.php:546
hasInitialValue(string $name)
Was a value available at construction time? (From settings.php)
Definition: Config.php:477
getInitialValue(string $name)
Get a value set at construction time.
Definition: Config.php:466
static factory(string $settings_path='')
Build a config from default settings locations.
Definition: Config.php:294
saveInitialValues(array $values)
Stores the inital values.
Definition: Config.php:278
static resolvePath(string $settings_path='')
Resolve settings path.
Definition: Config.php:366
wasWarnedLocked(string $name)
Log a read-only warning if the name is read-only.
Definition: Config.php:593
__set(string $name, $value)
Set an Elgg configuration value.
Definition: Config.php:502
__isset(string $name)
Handle isset()
Definition: Config.php:520
__unset(string $name)
Handle unset()
Definition: Config.php:530
getValues()
Get all values.
Definition: Config.php:379
__get(string $name)
Get an Elgg configuration value if it's been set or loaded during the boot process.
Definition: Config.php:431
A generic parent class for Configuration exceptions.
Find Elgg and project paths.
Definition: Paths.php:8
$config
Advanced site settings, debugging section.
Definition: debugging.php:6
elgg_deprecated_notice(string $msg, string $dep_version)
Log a notice about deprecated use of a function, view, etc.
Definition: elgglib.php:107
_elgg_services()
Get the global service provider.
Definition: elgglib.php:343
$value
Definition: generic.php:51
$path
Definition: details.php:70
if(parse_url(elgg_get_site_url(), PHP_URL_PATH) !=='/') if(file_exists(elgg_get_root_path() . 'robots.txt'))
Set robots.txt.
Definition: robots.php:10
$CONFIG wwwroot
The installation root URL of the site.
if(!isset($CONFIG)) $CONFIG dataroot
The full file path for Elgg data storage.