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 
141 class Config {
142 
143  use Loggable;
144 
145  private array $values = [];
146 
147  private array $initial_values = [];
148 
149  private bool $cookies_configured = false;
150 
151  private array $cookies = [];
152 
156  protected array $locked_values = [
157  'assetroot',
158  'cacheroot',
159  'dataroot',
160  'installed',
161  'plugins_path',
162  'wwwroot',
163  ];
164 
168  protected array $deprecated = [];
169 
173  protected array $config_defaults = [
174  'admin_validation_notification' => false,
175  'allow_phpinfo' => false,
176  'authentication_failures_lifetime' => 600,
177  'authentication_failures_limit' => 5,
178  'auto_disable_plugins' => true,
179  'batch_run_time_in_secs' => 4,
180  'boot_cache_ttl' => 3600,
181  'can_change_username' => false,
182  'class_loader_verify_file_existence' => true,
183  'comment_box_collapses' => true,
184  'comments_group_only' => true,
185  'comments_latest_first' => true,
186  'comments_max_depth' => 0,
187  'comments_per_page' => 25,
188  'db_enable_query_logging' => false,
189  'db_query_cache_limit' => 50,
190  'default_limit' => 10,
191  'elgg_maintenance_mode' => false,
192  'email_html_part' => true,
193  'email_html_part_images' => 'no',
194  'email_subject_limit' => 998,
195  'enable_delayed_email' => true,
196  'friendly_time_number_of_days' => 30,
197  'icon_sizes' => [
198  'topbar' => ['w' => 16, 'h' => 16, 'square' => true, 'upscale' => true],
199  'tiny' => ['w' => 25, 'h' => 25, 'square' => true, 'upscale' => true],
200  'small' => ['w' => 40, 'h' => 40, 'square' => true, 'upscale' => true],
201  'medium' => ['w' => 100, 'h' => 100, 'square' => true, 'upscale' => true],
202  'large' => ['w' => 200, 'h' => 200, 'square' => true, 'upscale' => true],
203  'master' => ['w' => 10240, 'h' => 10240, 'square' => false, 'upscale' => false, 'crop' => false],
204  ],
205  'language' => 'en',
206  'language_detect_from_browser' => true,
207  'lastcache' => 0,
208  'mentions_display_format' => 'display_name',
209  'message_delay' => 6,
210  'min_password_length' => 6,
211  'minusername' => 4,
212  'notifications_max_runtime' => 45,
213  'notifications_queue_delay' => 0,
214  'pagination_behaviour' => 'ajax-replace',
215  'require_admin_validation' => false,
216  'security_email_require_confirmation' => true,
217  'security_email_require_password' => true,
218  'security_notify_admins' => true,
219  'security_notify_user_password' => true,
220  'security_protect_upgrade' => true,
221  'session_bound_entity_icons' => false,
222  'simplecache_enabled' => false,
223  'subresource_integrity_enabled' => false,
224  'system_cache_enabled' => false,
225  'testing_mode' => false,
226  'trash_enabled' => true,
227  'trash_retention' => 30,
228  'user_joined_river' => false,
229  'webp_enabled' => true,
230  'who_can_change_language' => 'everyone',
231  ];
232 
236  protected array $path_properties = [
237  'assetroot',
238  'cacheroot',
239  'dataroot',
240  'plugins_path',
241  ];
242 
248  const ENTITY_TYPES = ['group', 'object', 'site', 'user'];
249 
255  const SENSITIVE_PROPERTIES = [
256  '__site_secret__',
257  'db',
258  'dbhost',
259  'dbport',
260  'dbuser',
261  'dbpass',
262  'dbname',
263  ];
264 
270  public function __construct(array $values = []) {
271  $this->saveInitialValues($values);
272 
273  $this->values = array_merge($this->config_defaults, $values);
274 
275  // set cookie values for session and remember me
276  $this->getCookieConfig();
277  }
278 
286  protected function saveInitialValues(array $values): void {
287  // Don't keep copies of these in case config gets dumped
288  foreach (self::SENSITIVE_PROPERTIES as $name) {
289  unset($values[$name]);
290  }
291 
292  $this->initial_values = $values;
293  }
294 
302  public static function factory(string $settings_path = ''): static {
303  $settings_path = self::resolvePath($settings_path);
304 
305  return self::fromFile($settings_path);
306  }
307 
316  protected static function fromFile($path): static {
317  if (!is_file($path)) {
318  throw new ConfigurationException(__METHOD__ . ": Reading configs failed: File {$path} not present.");
319  }
320 
321  if (!is_readable($path)) {
322  throw new ConfigurationException(__METHOD__ . ": Reading configs failed: File {$path} not readable.");
323  }
324 
325  // legacy loading. If $CONFIG doesn't exist, remove it after the
326  // settings file is read.
327  if (isset($GLOBALS['CONFIG'])) {
328  // don't overwrite it
329  $global = $GLOBALS['CONFIG'];
330  unset($GLOBALS['CONFIG']);
331  } else {
332  $global = null;
333  }
334 
335  Includer::requireFile($path);
336 
337  if (empty($GLOBALS['CONFIG']->dataroot)) {
338  throw new ConfigurationException(__METHOD__ . ': Reading configs failed: The Elgg settings file is missing $CONFIG->dataroot.');
339  }
340 
341  if (empty($GLOBALS['CONFIG']->wwwroot)) {
342  throw new ConfigurationException(__METHOD__ . ': Reading configs failed: The Elgg settings file is missing $CONFIG->wwwroot.');
343  }
344 
345  $config = new self(get_object_vars($GLOBALS['CONFIG']));
346 
347  if ($global !== null) {
348  // restore
349  $GLOBALS['CONFIG'] = $global;
350  } else {
351  unset($GLOBALS['CONFIG']);
352  }
353 
354  if ($config->{'X-Sendfile-Type'}) {
355  $config->{'x_sendfile_type'} = $config->{'X-Sendfile-Type'};
356  unset($config->{'X-Sendfile-Type'});
357  }
358 
359  if ($config->{'X-Accel-Mapping'}) {
360  $config->{'x_accel_mapping'} = $config->{'X-Accel-Mapping'};
361  unset($config->{'X-Accel-Mapping'});
362  }
363 
364  return $config;
365  }
366 
374  public static function resolvePath(string $settings_path = ''): string {
375  if (empty($settings_path)) {
376  $settings_path = Paths::settingsFile(Paths::SETTINGS_PHP);
377  }
378 
379  return Paths::sanitize($settings_path, false);
380  }
381 
387  public function getValues(): array {
388  return $this->values;
389  }
390 
396  public function getCookieConfig(): array {
397  if ($this->cookies_configured) {
398  return $this->cookies;
399  }
400 
401  $cookies = [];
402  if ($this->hasInitialValue('cookies')) {
403  $cookies = $this->getInitialValue('cookies');
404  }
405 
406  // session cookie config
407  if (!isset($cookies['session'])) {
408  $cookies['session'] = [];
409  }
410 
411  $session_defaults = session_get_cookie_params();
412  $session_defaults['name'] = 'Elgg';
413  $cookies['session'] = array_merge($session_defaults, $cookies['session']);
414 
415  // remember me cookie config
416  if (!isset($cookies['remember_me'])) {
417  $cookies['remember_me'] = [];
418  }
419 
420  $session_defaults['name'] = 'elggperm';
421  $session_defaults['expire'] = strtotime('+30 days');
422  $cookies['remember_me'] = array_merge($session_defaults, $cookies['remember_me']);
423 
424  $this->cookies = $cookies;
425  $this->cookies_configured = true;
426 
427  return $cookies;
428  }
429 
439  public function __get(string $name) {
440 
441  if (array_key_exists($name, $this->deprecated)) {
442  elgg_deprecated_notice("Using '{$name}' from config has been deprecated", $this->deprecated[$name]);
443  }
444 
445  if (!isset($this->values[$name])) {
446  return null;
447  }
448 
449  $value = $this->values[$name];
450  if (in_array($name, $this->path_properties)) {
451  $value = Paths::sanitize($value);
452  }
453 
454  return $value;
455  }
456 
464  public function hasValue(string $name): bool {
465  return isset($this->values[$name]);
466  }
467 
474  public function getInitialValue(string $name) {
475  return $this->initial_values[$name] ?? null;
476  }
477 
485  public function hasInitialValue(string $name): bool {
486  return isset($this->initial_values[$name]);
487  }
488 
496  public function isLocked(string $name): bool {
497  $testing = $this->values['testing_mode'] ?? false;
498  return !$testing && in_array($name, $this->locked_values) && $this->hasValue($name);
499  }
500 
510  public function __set(string $name, $value): void {
511  if ($this->wasWarnedLocked($name)) {
512  return;
513  }
514 
515  if (in_array($name, $this->path_properties)) {
516  $value = Paths::sanitize($value);
517  }
518 
519  $this->values[$name] = $value;
520  }
521 
528  public function __isset(string $name): bool {
529  return $this->__get($name) !== null;
530  }
531 
538  public function __unset(string $name): void {
539  if ($this->wasWarnedLocked($name)) {
540  return;
541  }
542 
543  unset($this->values[$name]);
544  }
545 
554  public function save(string $name, $value): bool {
555  if ($this->wasWarnedLocked($name)) {
556  return false;
557  }
558 
559  if (strlen($name) > 255) {
560  $this->getLogger()->error('The name length for configuration variables cannot be greater than 255');
561  return false;
562  }
563 
564  if ($value === null) {
565  // don't save null values
566  return $this->remove($name);
567  }
568 
569  $result = _elgg_services()->configTable->set($name, $value);
570 
571  $this->__set($name, $value);
572 
573  return $result;
574  }
575 
583  public function remove(string $name): bool {
584  if ($this->wasWarnedLocked($name)) {
585  return false;
586  }
587 
588  $result = _elgg_services()->configTable->remove($name);
589 
590  unset($this->values[$name]);
591 
592  return $result;
593  }
594 
601  protected function wasWarnedLocked(string $name): bool {
602  if (!$this->isLocked($name)) {
603  return false;
604  }
605 
606  $this->getLogger()->warning("The property {$name} is read-only.");
607 
608  return true;
609  }
610 }
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:464
isLocked(string $name)
Is this value locked?
Definition: Config.php:496
static fromFile($path)
Build a config from a file.
Definition: Config.php:316
__construct(array $values=[])
Constructor.
Definition: Config.php:270
getCookieConfig()
Set up and return the cookie configuration array resolved from settings.
Definition: Config.php:396
save(string $name, $value)
Save a configuration setting to the database.
Definition: Config.php:554
hasInitialValue(string $name)
Was a value available at construction time? (From settings.php)
Definition: Config.php:485
getInitialValue(string $name)
Get a value set at construction time.
Definition: Config.php:474
static factory(string $settings_path='')
Build a config from default settings locations.
Definition: Config.php:302
saveInitialValues(array $values)
Stores the inital values.
Definition: Config.php:286
static resolvePath(string $settings_path='')
Resolve settings path.
Definition: Config.php:374
wasWarnedLocked(string $name)
Log a read-only warning if the name is read-only.
Definition: Config.php:601
__set(string $name, $value)
Set an Elgg configuration value.
Definition: Config.php:510
__isset(string $name)
Handle isset()
Definition: Config.php:528
__unset(string $name)
Handle unset()
Definition: Config.php:538
getValues()
Get all values.
Definition: Config.php:387
__get(string $name)
Get an Elgg configuration value if it's been set or loaded during the boot process.
Definition: Config.php:439
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.