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 
134 class Config {
135 
136  use Loggable;
137 
138  private array $values = [];
139 
140  private array $initial_values = [];
141 
142  private bool $cookies_configured = false;
143 
144  private array $cookies = [];
145 
149  protected array $locked_values = [
150  'assetroot',
151  'cacheroot',
152  'dataroot',
153  'installed',
154  'plugins_path',
155  'wwwroot',
156  ];
157 
161  protected array $deprecated = [];
162 
166  protected array $config_defaults = [
167  'admin_validation_notification' => false,
168  'allow_phpinfo' => false,
169  'authentication_failures_lifetime' => 600,
170  'authentication_failures_limit' => 5,
171  'auto_disable_plugins' => true,
172  'batch_run_time_in_secs' => 4,
173  'boot_cache_ttl' => 3600,
174  'can_change_username' => false,
175  'class_loader_verify_file_existence' => true,
176  'comment_box_collapses' => true,
177  'comments_group_only' => true,
178  'comments_latest_first' => true,
179  'comments_max_depth' => 0,
180  'comments_per_page' => 25,
181  'db_enable_query_logging' => false,
182  'db_query_cache_limit' => 50,
183  'default_limit' => 10,
184  'elgg_maintenance_mode' => false,
185  'email_html_part' => true,
186  'email_html_part_images' => 'no',
187  'email_subject_limit' => 998,
188  'enable_delayed_email' => true,
189  'friendly_time_number_of_days' => 30,
190  'icon_sizes' => [
191  'topbar' => ['w' => 16, 'h' => 16, 'square' => true, 'upscale' => true],
192  'tiny' => ['w' => 25, 'h' => 25, 'square' => true, 'upscale' => true],
193  'small' => ['w' => 40, 'h' => 40, 'square' => true, 'upscale' => true],
194  'medium' => ['w' => 100, 'h' => 100, 'square' => true, 'upscale' => true],
195  'large' => ['w' => 200, 'h' => 200, 'square' => true, 'upscale' => true],
196  'master' => ['w' => 10240, 'h' => 10240, 'square' => false, 'upscale' => false, 'crop' => false],
197  ],
198  'language' => 'en',
199  'language_detect_from_browser' => true,
200  'lastcache' => 0,
201  'mentions_display_format' => 'display_name',
202  'message_delay' => 6,
203  'min_password_length' => 6,
204  'minusername' => 4,
205  'notifications_max_runtime' => 45,
206  'notifications_queue_delay' => 0,
207  'pagination_behaviour' => 'ajax-replace',
208  'require_admin_validation' => false,
209  'security_email_require_confirmation' => true,
210  'security_email_require_password' => true,
211  'security_notify_admins' => true,
212  'security_notify_user_password' => true,
213  'security_protect_upgrade' => true,
214  'session_bound_entity_icons' => false,
215  'simplecache_enabled' => false,
216  'subresource_integrity_enabled' => false,
217  'system_cache_enabled' => false,
218  'testing_mode' => false,
219  'trash_enabled' => true,
220  'trash_retention' => 30,
221  'user_joined_river' => false,
222  'webp_enabled' => true,
223  'who_can_change_language' => 'everyone',
224  ];
225 
229  protected array $path_properties = [
230  'assetroot',
231  'cacheroot',
232  'dataroot',
233  'plugins_path',
234  ];
235 
241  const ENTITY_TYPES = ['group', 'object', 'site', 'user'];
242 
248  const SENSITIVE_PROPERTIES = [
249  '__site_secret__',
250  'db',
251  'dbhost',
252  'dbport',
253  'dbuser',
254  'dbpass',
255  'dbname',
256  ];
257 
263  public function __construct(array $values = []) {
264  $this->saveInitialValues($values);
265 
266  $this->values = array_merge($this->config_defaults, $values);
267 
268  // set cookie values for session and remember me
269  $this->getCookieConfig();
270  }
271 
279  protected function saveInitialValues(array $values): void {
280  // Don't keep copies of these in case config gets dumped
281  foreach (self::SENSITIVE_PROPERTIES as $name) {
282  unset($values[$name]);
283  }
284 
285  $this->initial_values = $values;
286  }
287 
295  public static function factory(string $settings_path = ''): static {
296  $settings_path = self::resolvePath($settings_path);
297 
298  return self::fromFile($settings_path);
299  }
300 
309  protected static function fromFile($path): static {
310  if (!is_file($path)) {
311  throw new ConfigurationException(__METHOD__ . ": Reading configs failed: File {$path} not present.");
312  }
313 
314  if (!is_readable($path)) {
315  throw new ConfigurationException(__METHOD__ . ": Reading configs failed: File {$path} not readable.");
316  }
317 
318  // legacy loading. If $CONFIG doesn't exist, remove it after the
319  // settings file is read.
320  if (isset($GLOBALS['CONFIG'])) {
321  // don't overwrite it
322  $global = $GLOBALS['CONFIG'];
323  unset($GLOBALS['CONFIG']);
324  } else {
325  $global = null;
326  }
327 
328  Includer::requireFile($path);
329 
330  if (empty($GLOBALS['CONFIG']->dataroot)) {
331  throw new ConfigurationException(__METHOD__ . ': Reading configs failed: The Elgg settings file is missing $CONFIG->dataroot.');
332  }
333 
334  if (empty($GLOBALS['CONFIG']->wwwroot)) {
335  throw new ConfigurationException(__METHOD__ . ': Reading configs failed: The Elgg settings file is missing $CONFIG->wwwroot.');
336  }
337 
338  $config = new self(get_object_vars($GLOBALS['CONFIG']));
339 
340  if ($global !== null) {
341  // restore
342  $GLOBALS['CONFIG'] = $global;
343  } else {
344  unset($GLOBALS['CONFIG']);
345  }
346 
347  if ($config->{'X-Sendfile-Type'}) {
348  $config->{'x_sendfile_type'} = $config->{'X-Sendfile-Type'};
349  unset($config->{'X-Sendfile-Type'});
350  }
351 
352  if ($config->{'X-Accel-Mapping'}) {
353  $config->{'x_accel_mapping'} = $config->{'X-Accel-Mapping'};
354  unset($config->{'X-Accel-Mapping'});
355  }
356 
357  return $config;
358  }
359 
367  public static function resolvePath(string $settings_path = ''): string {
368  if (empty($settings_path)) {
369  $settings_path = Paths::settingsFile(Paths::SETTINGS_PHP);
370  }
371 
372  return Paths::sanitize($settings_path, false);
373  }
374 
380  public function getValues(): array {
381  return $this->values;
382  }
383 
389  public function getCookieConfig(): array {
390  if ($this->cookies_configured) {
391  return $this->cookies;
392  }
393 
394  $cookies = [];
395  if ($this->hasInitialValue('cookies')) {
396  $cookies = $this->getInitialValue('cookies');
397  }
398 
399  // session cookie config
400  if (!isset($cookies['session'])) {
401  $cookies['session'] = [];
402  }
403 
404  $session_defaults = session_get_cookie_params();
405  $session_defaults['name'] = 'Elgg';
406  $cookies['session'] = array_merge($session_defaults, $cookies['session']);
407 
408  // remember me cookie config
409  if (!isset($cookies['remember_me'])) {
410  $cookies['remember_me'] = [];
411  }
412 
413  $session_defaults['name'] = 'elggperm';
414  $session_defaults['expire'] = strtotime('+30 days');
415  $cookies['remember_me'] = array_merge($session_defaults, $cookies['remember_me']);
416 
417  $this->cookies = $cookies;
418  $this->cookies_configured = true;
419 
420  return $cookies;
421  }
422 
432  public function __get(string $name) {
433 
434  if (array_key_exists($name, $this->deprecated)) {
435  elgg_deprecated_notice("Using '{$name}' from config has been deprecated", $this->deprecated[$name]);
436  }
437 
438  if (!isset($this->values[$name])) {
439  return null;
440  }
441 
442  $value = $this->values[$name];
443  if (in_array($name, $this->path_properties)) {
444  $value = Paths::sanitize($value);
445  }
446 
447  return $value;
448  }
449 
457  public function hasValue(string $name): bool {
458  return isset($this->values[$name]);
459  }
460 
467  public function getInitialValue(string $name) {
468  return $this->initial_values[$name] ?? null;
469  }
470 
478  public function hasInitialValue(string $name): bool {
479  return isset($this->initial_values[$name]);
480  }
481 
489  public function isLocked(string $name): bool {
490  $testing = $this->values['testing_mode'] ?? false;
491  return !$testing && in_array($name, $this->locked_values) && $this->hasValue($name);
492  }
493 
503  public function __set(string $name, $value): void {
504  if ($this->wasWarnedLocked($name)) {
505  return;
506  }
507 
508  if (in_array($name, $this->path_properties)) {
509  $value = Paths::sanitize($value);
510  }
511 
512  $this->values[$name] = $value;
513  }
514 
521  public function __isset(string $name): bool {
522  return $this->__get($name) !== null;
523  }
524 
531  public function __unset(string $name): void {
532  if ($this->wasWarnedLocked($name)) {
533  return;
534  }
535 
536  unset($this->values[$name]);
537  }
538 
547  public function save(string $name, $value): bool {
548  if ($this->wasWarnedLocked($name)) {
549  return false;
550  }
551 
552  if (strlen($name) > 255) {
553  $this->getLogger()->error('The name length for configuration variables cannot be greater than 255');
554  return false;
555  }
556 
557  if ($value === null) {
558  // don't save null values
559  return $this->remove($name);
560  }
561 
562  $result = _elgg_services()->configTable->set($name, $value);
563 
564  $this->__set($name, $value);
565 
566  return $result;
567  }
568 
576  public function remove(string $name): bool {
577  if ($this->wasWarnedLocked($name)) {
578  return false;
579  }
580 
581  $result = _elgg_services()->configTable->remove($name);
582 
583  unset($this->values[$name]);
584 
585  return $result;
586  }
587 
594  protected function wasWarnedLocked(string $name): bool {
595  if (!$this->isLocked($name)) {
596  return false;
597  }
598 
599  $this->getLogger()->warning("The property {$name} is read-only.");
600 
601  return true;
602  }
603 }
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:457
isLocked(string $name)
Is this value locked?
Definition: Config.php:489
static fromFile($path)
Build a config from a file.
Definition: Config.php:309
__construct(array $values=[])
Constructor.
Definition: Config.php:263
getCookieConfig()
Set up and return the cookie configuration array resolved from settings.
Definition: Config.php:389
save(string $name, $value)
Save a configuration setting to the database.
Definition: Config.php:547
hasInitialValue(string $name)
Was a value available at construction time? (From settings.php)
Definition: Config.php:478
getInitialValue(string $name)
Get a value set at construction time.
Definition: Config.php:467
static factory(string $settings_path='')
Build a config from default settings locations.
Definition: Config.php:295
saveInitialValues(array $values)
Stores the inital values.
Definition: Config.php:279
static resolvePath(string $settings_path='')
Resolve settings path.
Definition: Config.php:367
wasWarnedLocked(string $name)
Log a read-only warning if the name is read-only.
Definition: Config.php:594
__set(string $name, $value)
Set an Elgg configuration value.
Definition: Config.php:503
__isset(string $name)
Handle isset()
Definition: Config.php:521
__unset(string $name)
Handle unset()
Definition: Config.php:531
getValues()
Get all values.
Definition: Config.php:380
__get(string $name)
Get an Elgg configuration value if it's been set or loaded during the boot process.
Definition: Config.php:432
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.