Elgg  Version master
Config.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg;
4 
8 
127 class Config {
128 
129  use Loggable;
130 
134  private $values;
135 
139  private $initial_values;
140 
144  private $cookies_configured = false;
145 
149  private $cookies = [];
150 
156  protected $locked_values = [
157  'assetroot',
158  'cacheroot',
159  'dataroot',
160  'installed',
161  'plugins_path',
162  'wwwroot',
163  ];
164 
170  protected $deprecated = [
171  ];
172 
178  protected $config_defaults = [
179  'allow_phpinfo' => false,
180  'authentication_failures_lifetime' => 600,
181  'authentication_failures_limit' => 5,
182  'auto_disable_plugins' => true,
183  'batch_run_time_in_secs' => 4,
184  'boot_cache_ttl' => 3600,
185  'can_change_username' => false,
186  'class_loader_verify_file_existence' => true,
187  'comment_box_collapses' => true,
188  'comments_group_only' => true,
189  'comments_latest_first' => true,
190  'comments_max_depth' => 0,
191  'comments_per_page' => 25,
192  'db_query_cache_limit' => 50,
193  'default_limit' => 10,
194  'elgg_maintenance_mode' => false,
195  'email_html_part' => true,
196  'email_html_part_images' => 'no',
197  'email_subject_limit' => 998,
198  'enable_delayed_email' => true,
199  'friendly_time_number_of_days' => 30,
200  'icon_sizes' => [
201  'topbar' => ['w' => 16, 'h' => 16, 'square' => true, 'upscale' => true],
202  'tiny' => ['w' => 25, 'h' => 25, 'square' => true, 'upscale' => true],
203  'small' => ['w' => 40, 'h' => 40, 'square' => true, 'upscale' => true],
204  'medium' => ['w' => 100, 'h' => 100, 'square' => true, 'upscale' => true],
205  'large' => ['w' => 200, 'h' => 200, 'square' => true, 'upscale' => true],
206  'master' => ['w' => 10240, 'h' => 10240, 'square' => false, 'upscale' => false, 'crop' => false],
207  ],
208  'language' => 'en',
209  'language_detect_from_browser' => true,
210  'lastcache' => 0,
211  'message_delay' => 6,
212  'min_password_length' => 6,
213  'minusername' => 4,
214  'notifications_max_runtime' => 45,
215  'notifications_queue_delay' => 0,
216  'pagination_behaviour' => 'ajax-replace',
217  'security_email_require_confirmation' => true,
218  'security_email_require_password' => true,
219  'security_notify_admins' => true,
220  'security_notify_user_password' => true,
221  'security_protect_upgrade' => true,
222  'session_bound_entity_icons' => false,
223  'simplecache_enabled' => false,
224  'subresource_integrity_enabled' => false,
225  'system_cache_enabled' => false,
226  'testing_mode' => false,
227  'webp_enabled' => true,
228  'who_can_change_language' => 'everyone',
229  ];
230 
236  protected $path_properties = [
237  'dataroot',
238  'cacheroot',
239  'assetroot',
240  ];
241 
247  const ENTITY_TYPES = ['group', 'object', 'site', 'user'];
248 
254  const SENSITIVE_PROPERTIES = [
255  '__site_secret__',
256  'db',
257  'dbhost',
258  'dbport',
259  'dbuser',
260  'dbpass',
261  'dbname',
262  ];
263 
269  public function __construct(array $values = []) {
270  $this->saveInitialValues($values);
271 
272  $this->values = array_merge($this->config_defaults, $values);
273 
274  // set cookie values for session and remember me
275  $this->getCookieConfig();
276  }
277 
285  protected function saveInitialValues(array $values): void {
286  // Don't keep copies of these in case config gets dumped
287  foreach (self::SENSITIVE_PROPERTIES as $name) {
288  unset($values[$name]);
289  }
290 
291  $this->initial_values = $values;
292  }
293 
303  public static function factory(string $settings_path = '', bool $try_env = true): static {
304  $reason1 = '';
305 
306  $settings_path = self::resolvePath($settings_path, $try_env);
307 
308  $config = self::fromFile($settings_path, $reason1);
309 
310  if (!$config) {
311  throw new ConfigurationException(__METHOD__ . ": Reading configs failed: $reason1");
312  }
313 
314  return $config;
315  }
316 
325  public static function fromFile($path, &$reason = '') {
326  if (!is_file($path)) {
327  $reason = "File $path not present.";
328  return false;
329  }
330 
331  if (!is_readable($path)) {
332  $reason = "File $path not readable.";
333  return false;
334  }
335 
336  // legacy loading. If $CONFIG doesn't exist, remove it after the
337  // settings file is read.
338  if (isset($GLOBALS['CONFIG'])) {
339  // don't overwrite it
340  $global = $GLOBALS['CONFIG'];
341  unset($GLOBALS['CONFIG']);
342  } else {
343  $global = null;
344  }
345 
346  Includer::requireFile($path);
347 
348  if (empty($GLOBALS['CONFIG']->dataroot)) {
349  $reason = 'The Elgg settings file is missing $CONFIG->dataroot.';
350  return false;
351  }
352 
353  if (empty($GLOBALS['CONFIG']->wwwroot)) {
354  $reason = 'The Elgg settings file is missing $CONFIG->wwwroot.';
355  return false;
356  }
357 
358  $config = new self(get_object_vars($GLOBALS['CONFIG']));
359 
360  if ($global !== null) {
361  // restore
362  $GLOBALS['CONFIG'] = $global;
363  } else {
364  unset($GLOBALS['CONFIG']);
365  }
366 
367  if ($config->{'X-Sendfile-Type'}) {
368  $config->{'x_sendfile_type'} = $config->{'X-Sendfile-Type'};
369  unset($config->{'X-Sendfile-Type'});
370  }
371  if ($config->{'X-Accel-Mapping'}) {
372  $config->{'x_accel_mapping'} = $config->{'X-Accel-Mapping'};
373  unset($config->{'X-Accel-Mapping'});
374  }
375 
376  return $config;
377  }
378 
386  public static function resolvePath(string $settings_path = '', bool $try_env = true): string {
387  if (!$settings_path) {
388  if ($try_env && !empty(getenv('ELGG_SETTINGS_FILE'))) {
389  $settings_path = getenv('ELGG_SETTINGS_FILE');
390  } else if (!$settings_path) {
391  $settings_path = Paths::settingsFile(Paths::SETTINGS_PHP);
392  }
393  }
394 
395  return \Elgg\Project\Paths::sanitize($settings_path, false);
396  }
397 
403  public function getValues(): array {
404  return $this->values;
405  }
406 
412  public function getCookieConfig(): array {
413  if ($this->cookies_configured) {
414  return $this->cookies;
415  }
416 
417  $cookies = [];
418  if ($this->hasInitialValue('cookies')) {
419  $cookies = $this->getInitialValue('cookies');
420  }
421 
422  // session cookie config
423  if (!isset($cookies['session'])) {
424  $cookies['session'] = [];
425  }
426  $session_defaults = session_get_cookie_params();
427  $session_defaults['name'] = 'Elgg';
428  $cookies['session'] = array_merge($session_defaults, $cookies['session']);
429 
430  // remember me cookie config
431  if (!isset($cookies['remember_me'])) {
432  $cookies['remember_me'] = [];
433  }
434  $session_defaults['name'] = 'elggperm';
435  $session_defaults['expire'] = strtotime("+30 days");
436  $cookies['remember_me'] = array_merge($session_defaults, $cookies['remember_me']);
437 
438  $this->cookies = $cookies;
439  $this->cookies_configured = true;
440 
441  return $cookies;
442  }
443 
453  public function __get(string $name) {
454 
455  if (array_key_exists($name, $this->deprecated)) {
456  elgg_deprecated_notice("Using '{$name}' from config has been deprecated", $this->deprecated[$name]);
457  }
458 
459  if (isset($this->values[$name])) {
460  return $this->values[$name];
461  }
462 
463  return null;
464  }
465 
473  public function hasValue(string $name): bool {
474  return isset($this->values[$name]);
475  }
476 
483  public function getInitialValue(string $name) {
484  return $this->initial_values[$name] ?? null;
485  }
486 
494  public function hasInitialValue(string $name): bool {
495  return isset($this->initial_values[$name]);
496  }
497 
505  public function isLocked(string $name): bool {
506  $testing = $this->values['testing_mode'] ?? false;
507  return !$testing && in_array($name, $this->locked_values) && $this->hasValue($name);
508  }
509 
519  public function __set(string $name, $value): void {
520  if ($this->wasWarnedLocked($name)) {
521  return;
522  }
523 
524  if (in_array($name, $this->path_properties)) {
525  $value = Paths::sanitize($value);
526  }
527 
528  $this->values[$name] = $value;
529  }
530 
537  public function __isset(string $name): bool {
538  return $this->__get($name) !== null;
539  }
540 
547  public function __unset(string $name): void {
548  if ($this->wasWarnedLocked($name)) {
549  return;
550  }
551 
552  unset($this->values[$name]);
553  }
554 
563  public function save(string $name, $value): bool {
564  if ($this->wasWarnedLocked($name)) {
565  return false;
566  }
567 
568  if (strlen($name) > 255) {
569  $this->getLogger()->error("The name length for configuration variables cannot be greater than 255");
570  return false;
571  }
572 
573  if ($value === null) {
574  // don't save null values
575  return $this->remove($name);
576  }
577 
578  $result = _elgg_services()->configTable->set($name, $value);
579 
580  $this->__set($name, $value);
581 
582  return $result;
583  }
584 
592  public function remove(string $name): bool {
593  if ($this->wasWarnedLocked($name)) {
594  return false;
595  }
596 
597  $result = _elgg_services()->configTable->remove($name);
598 
599  unset($this->values[$name]);
600 
601  return $result;
602  }
603 
610  protected function wasWarnedLocked(string $name): bool {
611  if (!$this->isLocked($name)) {
612  return false;
613  }
614 
615  $this->getLogger()->warning("The property {$name} is read-only.");
616 
617  return true;
618  }
619 }
hasInitialValue(string $name)
Was a value available at construction time? (From settings.php)
Definition: Config.php:494
A generic parent class for Configuration exceptions.
if(!isset($CONFIG)) $CONFIG dataroot
The full file path for Elgg data storage.
elgg_deprecated_notice(string $msg, string $dep_version)
Log a notice about deprecated use of a function, view, etc.
Definition: elgglib.php:115
saveInitialValues(array $values)
Stores the inital values.
Definition: Config.php:285
save(string $name, $value)
Save a configuration setting to the database.
Definition: Config.php:563
if(!$user||!$user->canDelete()) $name
Definition: delete.php:22
static factory(string $settings_path= '', bool $try_env=true)
Build a config from default settings locations.
Definition: Config.php:303
c Accompany it with the information you received as to the offer to distribute corresponding source complete source code means all the source code for all modules it plus any associated interface definition plus the scripts used to control compilation and installation of the executable as a special the source code distributed need not include anything that is normally and so on of the operating system on which the executable unless that component itself accompanies the executable If distribution of executable or object code is made by offering access to copy from a designated then offering equivalent access to copy the source code from the same place counts as distribution of the source even though third parties are not compelled to copy the source along with the object code You may not or distribute the Program except as expressly provided under this License Any attempt otherwise to sublicense or distribute the Program is void
Definition: LICENSE.txt:215
wasWarnedLocked(string $name)
Log a read-only warning if the name is read-only.
Definition: Config.php:610
__get(string $name)
Get an Elgg configuration value if it&#39;s been set or loaded during the boot process.
Definition: Config.php:453
hasValue(string $name)
Test if we have a set value.
Definition: Config.php:473
__set(string $name, $value)
Set an Elgg configuration value.
Definition: Config.php:519
$value
Definition: generic.php:51
__construct(array $values=[])
Constructor.
Definition: Config.php:269
$config
Advanced site settings, debugging section.
Definition: debugging.php:6
$path
Definition: details.php:68
trait Loggable
Enables adding a logger.
Definition: Loggable.php:14
__unset(string $name)
Handle unset()
Definition: Config.php:547
__isset(string $name)
Handle isset()
Definition: Config.php:537
isLocked(string $name)
Is this value locked?
Definition: Config.php:505
static resolvePath(string $settings_path= '', bool $try_env=true)
Resolve settings path.
Definition: Config.php:386
getLogger()
Returns logger.
Definition: Loggable.php:37
getCookieConfig()
Set up and return the cookie configuration array resolved from settings.
Definition: Config.php:412
static fromFile($path, &$reason= '')
Build a config from a file.
Definition: Config.php:325
getValues()
Get all values.
Definition: Config.php:403
getInitialValue(string $name)
Get a value set at construction time.
Definition: Config.php:483
_elgg_services()
Get the global service provider.
Definition: elgglib.php:347
$CONFIG wwwroot
The installation root URL of the site.