NobGit
public nobgit read

NobMail

Based on mailcow: dockerized

Languages

Repository composition by tracked source files.

PHP
PHP 49% JavaScript 35% HTML 9% CSS 4% Shell 2% Python 1% Lua 0% Perl 0% Ruby 0% SCSS 0%
Create file Wiki Documentation
Clone
https://nobgit.com/orgs/nobgit/nobmail.git
ssh://[email protected]:2222/orgs/nobgit/nobmail.git

Commit

[Web] Some minor fixes and improvements for PHP 8

cf8fdae2
andryyy <[email protected]> 5 years ago
data/web/admin.php                                 |  26 +-
 data/web/css/build/014-responsive.css              |   1 -
 data/web/debug.php                                 |   2 +-
 data/web/develcow.de/index.html                    |   1 +
 data/web/inc/functions.inc.php                     | 686 +++++++++--------
 data/web/inc/header.inc.php                        |   2 +-
 data/web/inc/lib/composer.json                     |   2 +-
 data/web/inc/lib/composer.lock                     | 128 ++--
 data/web/inc/lib/vendor/composer/ClassLoader.php   |   4 +-
 .../inc/lib/vendor/composer/InstalledVersions.php  | 851 ++++++++-------------
 .../web/inc/lib/vendor/composer/autoload_files.php |   2 +-
 .../inc/lib/vendor/composer/autoload_static.php    |   2 +-
 data/web/inc/lib/vendor/composer/installed.json    | 142 ++--
 data/web/inc/lib/vendor/composer/installed.php     | 512 ++++++-------
 .../.github/ISSUE_TEMPLATE/bug_report.md           |   5 +-
 .../ISSUE_TEMPLATE/support---help-request.md       |   5 +
 .../ldaprecord/.github/workflows/run-tests.yml     |   7 +-
 .../Configuration/Validators/ArrayValidator.php    |  17 +-
 .../Configuration/Validators/BooleanValidator.php  |  17 +-
 .../Configuration/Validators/IntegerValidator.php  |  17 +-
 .../Validators/StringOrNullValidator.php           |  17 +-
 .../src/Configuration/Validators/Validator.php     |  43 +-
 .../directorytree/ldaprecord/src/Connection.php    |   2 +-
 .../ldaprecord/src/ConnectionManager.php           | 320 ++++++++
 .../directorytree/ldaprecord/src/Container.php     | 376 ++-------
 .../directorytree/ldaprecord/src/Events/Logger.php |   2 +-
 .../src/{LdapBase.php => HandlesConnection.php}    |  12 +-
 .../vendor/directorytree/ldaprecord/src/Ldap.php   |  50 +-
 .../directorytree/ldaprecord/src/LdapInterface.php |  59 +-
 .../src/Models/Attributes/AccountControl.php       |   2 +-
 .../src/Models/Attributes/DistinguishedName.php    | 111 ++-
 .../Models/Attributes/DistinguishedNameBuilder.php |   2 +-
 .../ldaprecord/src/Models/Attributes/Guid.php      |   6 +-
 .../ldaprecord/src/Models/Concerns/HasPassword.php |  10 +-
 .../src/Models/Concerns/HidesAttributes.php        |   2 +-
 .../directorytree/ldaprecord/src/Models/Model.php  |  39 +-
 .../ldaprecord/src/Models/Relations/HasMany.php    |  16 +
 .../ldaprecord/src/Models/Relations/OneToMany.php  |  43 +-
 .../src/Models/Types/ActiveDirectory.php           |   2 +-
 .../ldaprecord/src/Query/ArrayCacheStore.php       |  26 +-
 .../directorytree/ldaprecord/src/Query/Cache.php   |   8 +-
 .../ldaprecord/src/Query/InteractsWithTime.php     |  22 +-
 .../src/Query/Pagination/DeprecatedPaginator.php   |   2 +-
 .../ldaprecord/src/Testing/ConnectionFake.php      |   6 +-
 .../ldaprecord/src/Testing/LdapExpectation.php     |   4 +-
 .../ldaprecord/src/Testing/LdapFake.php            |  24 +-
 .../directorytree/ldaprecord/src/Utilities.php     |   4 +-
 .../illuminate/contracts/Support/MessageBag.php    |  11 +-
 .../web/inc/lib/vendor/nesbot/carbon/composer.json |  85 +-
 .../inc/lib/vendor/nesbot/carbon/contributing.md   | 154 ----
 data/web/inc/lib/vendor/nesbot/carbon/phpmd.xml    |  46 --
 data/web/inc/lib/vendor/nesbot/carbon/readme.md    |   8 +-
 .../nesbot/carbon/src/Carbon/CarbonImmutable.php   |  10 +
 .../nesbot/carbon/src/Carbon/CarbonInterface.php   |  31 +-
 .../nesbot/carbon/src/Carbon/CarbonInterval.php    |  28 +-
 .../nesbot/carbon/src/Carbon/CarbonPeriod.php      |  38 +-
 .../nesbot/carbon/src/Carbon/CarbonTimeZone.php    |   2 +-
 .../src/Carbon/Doctrine/CarbonTypeConverter.php    |   4 +-
 .../vendor/nesbot/carbon/src/Carbon/Factory.php    |   4 +-
 .../nesbot/carbon/src/Carbon/FactoryImmutable.php  |   2 +-
 .../vendor/nesbot/carbon/src/Carbon/Lang/be.php    |   2 +-
 .../vendor/nesbot/carbon/src/Carbon/Lang/bn_BD.php |   2 +-
 .../vendor/nesbot/carbon/src/Carbon/Lang/gl.php    |   2 +-
 .../vendor/nesbot/carbon/src/Carbon/Lang/ka.php    |   4 +-
 .../vendor/nesbot/carbon/src/Carbon/Lang/nl.php    |   2 +-
 .../vendor/nesbot/carbon/src/Carbon/Lang/oc.php    |   2 +-
 .../vendor/nesbot/carbon/src/Carbon/Lang/pl.php    |   2 +-
 .../vendor/nesbot/carbon/src/Carbon/Lang/sh.php    |   2 +-
 .../nesbot/carbon/src/Carbon/Lang/shn_MM.php       |   2 +-
 .../vendor/nesbot/carbon/src/Carbon/Language.php   |   2 +
 .../nesbot/carbon/src/Carbon/Traits/Comparison.php |  10 +-
 .../nesbot/carbon/src/Carbon/Traits/Converter.php  |  12 +-
 .../nesbot/carbon/src/Carbon/Traits/Creator.php    |   6 +-
 .../nesbot/carbon/src/Carbon/Traits/Date.php       |  78 +-
 .../nesbot/carbon/src/Carbon/Traits/Difference.php |  40 +-
 .../carbon/src/Carbon/Traits/IntervalStep.php      |   2 +-
 .../carbon/src/Carbon/Traits/Localization.php      |  10 +-
 .../nesbot/carbon/src/Carbon/Traits/Modifiers.php  |  14 +-
 .../src/Carbon/Traits/ObjectInitialisation.php     |   2 +-
 .../nesbot/carbon/src/Carbon/Traits/Options.php    |  26 +-
 .../nesbot/carbon/src/Carbon/Traits/Rounding.php   |   9 +-
 .../carbon/src/Carbon/Traits/Serialization.php     |  48 +-
 .../nesbot/carbon/src/Carbon/Traits/Test.php       |   6 +-
 .../nesbot/carbon/src/Carbon/Traits/Timestamp.php  |  17 +-
 .../nesbot/carbon/src/Carbon/Traits/Units.php      |  23 +-
 .../nesbot/carbon/src/Carbon/Traits/Week.php       |  16 +-
 .../vendor/nesbot/carbon/src/Carbon/Translator.php |   6 +-
 .../.github/workflows/main.yml                     |  60 ++
 .../php-mime-mail-parser/README.md                 |  13 +-
 .../php-mime-mail-parser/composer.json             |  11 +-
 .../vendor/symfony/polyfill-mbstring/Mbstring.php  |  11 +-
 .../lib/vendor/symfony/polyfill-php80/README.md    |   2 +-
 .../vendor/symfony/polyfill-php80/bootstrap.php    |   6 +-
 .../translation/Command/TranslationPushCommand.php |   6 +-
 .../DependencyInjection/TranslatorPathsPass.php    |   3 +
 .../symfony/translation/Dumper/XliffFileDumper.php |   6 +-
 .../Exception/IncompleteDsnException.php           |   2 +-
 .../Exception/MissingRequiredOptionException.php   |   2 +-
 .../translation/Extractor/ChainExtractor.php       |   2 -
 .../translation/Extractor/ExtractorInterface.php   |   4 +-
 .../translation/Extractor/PhpStringTokenParser.php |   2 +-
 .../symfony/translation/Loader/CsvFileLoader.php   |   2 +-
 .../symfony/translation/Loader/FileLoader.php      |   4 +-
 .../symfony/translation/Loader/IniFileLoader.php   |   2 +-
 .../symfony/translation/Loader/JsonFileLoader.php  |   2 +-
 .../symfony/translation/Loader/MoFileLoader.php    |   6 +-
 .../symfony/translation/Loader/PhpFileLoader.php   |   2 +-
 .../symfony/translation/Loader/PoFileLoader.php    |   2 +-
 .../symfony/translation/Loader/XliffFileLoader.php |   2 +-
 .../symfony/translation/Loader/YamlFileLoader.php  |   2 +-
 .../symfony/translation/MessageCatalogue.php       |  18 +-
 .../symfony/translation/MetadataAwareInterface.php |  10 +-
 .../Resources/bin/translation-status.php           |   2 +-
 .../lib/vendor/symfony/translation/Translator.php  |  11 +-
 .../translation/Writer/TranslationWriter.php       |   4 +-
 .../lib/vendor/symfony/translation/composer.json   |   4 +-
 .../vendor/symfony/var-dumper/Caster/ClassStub.php |   4 +-
 .../vendor/symfony/var-dumper/Caster/DOMCaster.php |   2 +-
 .../symfony/var-dumper/Caster/ExceptionCaster.php  |   4 +-
 .../vendor/symfony/var-dumper/Caster/LinkStub.php  |  10 +-
 .../symfony/var-dumper/Caster/MemcachedCaster.php  |   2 +-
 .../symfony/var-dumper/Caster/RdKafkaCaster.php    |  20 +-
 .../symfony/var-dumper/Caster/ReflectionCaster.php |   6 +-
 .../symfony/var-dumper/Caster/ResourceCaster.php   |   4 +-
 .../vendor/symfony/var-dumper/Caster/SplCaster.php |   4 +-
 .../symfony/var-dumper/Cloner/AbstractCloner.php   |   2 +-
 .../lib/vendor/symfony/var-dumper/Cloner/Data.php  |   9 +
 .../symfony/var-dumper/Dumper/AbstractDumper.php   |   2 +-
 .../vendor/symfony/var-dumper/Dumper/CliDumper.php |  10 +-
 .../ContextProvider/SourceContextProvider.php      |   4 +-
 .../symfony/var-dumper/Dumper/HtmlDumper.php       |  17 +-
 .../symfony/var-dumper/Server/Connection.php       |   4 +-
 .../symfony/var-dumper/Server/DumpServer.php       |   2 +-
 .../lib/vendor/symfony/var-dumper/composer.json    |   2 +-
 data/web/inc/triggers.inc.php                      |   2 +-
 data/web/inc/vars.inc.php                          |  14 +-
 data/web/index.php                                 |   2 +-
 data/web/modals/admin.php                          |   2 +-
 138 files changed, 2398 insertions(+), 2342 deletions(-)
 create mode 100644 data/web/develcow.de/index.html
 create mode 100644 data/web/inc/lib/vendor/directorytree/ldaprecord/src/ConnectionManager.php
 rename data/web/inc/lib/vendor/directorytree/ldaprecord/src/{LdapBase.php => HandlesConnection.php} (95%)
 delete mode 100644 data/web/inc/lib/vendor/nesbot/carbon/contributing.md
 delete mode 100644 data/web/inc/lib/vendor/nesbot/carbon/phpmd.xml
 create mode 100644 data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/.github/workflows/main.yml

Diff

diff --git a/data/web/admin.php b/data/web/admin.php
index 98a7ddd5..7ef0ca57 100644
--- a/data/web/admin.php
+++ b/data/web/admin.php
@@ -81,7 +81,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
         <div class="row">
           <div class="col-sm-3 col-xs-5 text-right"><?=$lang['tfa']['tfa'];?>:</div>
           <div class="col-sm-9 col-xs-7">
-            <p id="tfa_pretty"><?=$tfa_data['pretty'];?></p>
+            <p id="tfa_pretty"><?=(isset($tfa_data['pretty'])) ? $tfa_data['pretty'] : '';?></p>
               <div id="tfa_keys">
                 <?php
                 if (!empty($tfa_data['additional'])) {
@@ -133,7 +133,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
                 ?>
                 <tr>
                   <td>
-                    <?=($_SESSION['fido2_cid'] == $key_info['cid']) ? '<i class="bi bi-unlock-fill"></i> ' : NULL; ?><?=(!empty($key_info['fn']))?$key_info['fn']:$key_info['subject'];?>
+                    <?=(isset($_SESSION['fido2_cid']) && $_SESSION['fido2_cid'] == $key_info['cid']) ? '<i class="bi bi-unlock-fill"></i> ' : NULL; ?><?=(!empty($key_info['fn']))?$key_info['fn']:$key_info['subject'];?>
                   </td>
                   <td style="min-width:240px;text-align: right">
                     <form style="display:inline;" method="post">
@@ -222,13 +222,13 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
                     <div class="form-group">
                       <label class="control-label col-sm-3" for="allow_from_ro"><?=$lang['admin']['api_allow_from'];?>:</label>
                       <div class="col-sm-9">
-                        <textarea class="form-control textarea-code" rows="7" name="allow_from" id="allow_from_ro" <?=($api_ro['skip_ip_check'] == 1) ? 'disabled' : null;?> required><?=htmlspecialchars($api_ro['allow_from']);?></textarea>
+                        <textarea class="form-control textarea-code" rows="7" name="allow_from" id="allow_from_ro" <?=(isset($api_ro['skip_ip_check']) && $api_ro['skip_ip_check'] == 1) ? 'disabled' : null;?> required><?=(isset($api_ro['allow_from'])) ? htmlspecialchars($api_ro['allow_from']) : '';?></textarea>
                       </div>
                     </div>
                     <div class="form-group">
                       <div class="col-sm-offset-3 col-sm-9">
                         <label>
-                          <input type="checkbox" name="skip_ip_check" id="skip_ip_check_ro" <?=($api_ro['skip_ip_check'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['api_skip_ip_check'];?>
+                          <input type="checkbox" name="skip_ip_check" id="skip_ip_check_ro" <?=(isset($api_ro['skip_ip_check']) && $api_ro['skip_ip_check'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['api_skip_ip_check'];?>
                         </label>
                       </div>
                     </div>
@@ -241,7 +241,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
                     <div class="form-group">
                       <div class="col-sm-offset-3 col-sm-9">
                         <label>
-                          <input type="checkbox" name="active" <?=($api_ro['active'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['activate_api'];?>
+                          <input type="checkbox" name="active" <?=(isset($api_ro['active']) && $api_ro['active'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['activate_api'];?>
                         </label>
                       </div>
                     </div>
@@ -1174,15 +1174,17 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
             </tr>
             <?php
             $app_links = customize('get', 'app_links');
-            foreach ($app_links as $row) {
-              foreach ($row as $key => $val) {
-            ?>
+            if ($app_links) {
+              foreach ($app_links as $row) {
+                foreach ($row as $key => $val) {
+              ?>
             <tr>
               <td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="app" required value="<?=$key;?>"></td>
               <td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="href" required value="<?=$val;?>"></td>
               <td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-default" type="button"><?=$lang['admin']['remove_row'];?></a></td>
             </tr>
             <?php
+                }
               }
             }
             foreach ($MAILCOW_APPS as $app) {
@@ -1433,7 +1435,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
       </div>
       <div class="panel-body">
         <p><?=$lang['admin']['rspamd_global_filters_info'];?></p>
-        <div id="confirm_show_rspamd_global_filters" class="<?=($_SESSION['show_rspamd_global_filters'] === true) ? 'hidden' : '';?>">
+        <div id="confirm_show_rspamd_global_filters" class="<?=(isset($_SESSION['show_rspamd_global_filters']) && $_SESSION['show_rspamd_global_filters'] === true) ? 'hidden' : '';?>">
           <div class="form-group">
             <div class="col-sm-offset-2 col-sm-10">
               <label>
@@ -1442,7 +1444,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
             </div>
           </div>
         </div>
-        <div id="rspamd_global_filters" class="<?=($_SESSION['show_rspamd_global_filters'] !== true) ? 'hidden' : '';?>">
+        <div id="rspamd_global_filters" class="<?=(isset($_SESSION['show_rspamd_global_filters']) && $_SESSION['show_rspamd_global_filters'] === true) ? 'hidden' : '';?>">
         <hr>
         <span class="anchor" id="regexmaps"></span>
         <h4><?=$lang['admin']['regex_maps'];?></h4>
@@ -1506,7 +1508,7 @@ $js_minifier->add('/web/js/presets/rspamd.js');
 $js_minifier->add('/web/js/site/pwgen.js');
 require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
 } else {
-	header('Location: /');
-	exit();
+  header('Location: /');
+  exit();
 }
 ?>
diff --git a/data/web/css/build/014-responsive.css b/data/web/css/build/014-responsive.css
index 4dd38cac..060b37c4 100644
--- a/data/web/css/build/014-responsive.css
+++ b/data/web/css/build/014-responsive.css
@@ -14,7 +14,6 @@
   width: auto;
   float: left;
   margin-right: 10px;
-  margin-top: auto;
 }
 
 
diff --git a/data/web/debug.php b/data/web/debug.php
index 093e8b59..f8ad527e 100644
--- a/data/web/debug.php
+++ b/data/web/debug.php
@@ -76,7 +76,7 @@ $clamd_status = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["SKIP_CLAMD"])) ?
                   <div class="progress">
                     <div class="progress-bar progress-bar-info" role="progressbar" style="width:<?=round($solr_status['jvm']['memory']['raw']['used%']);?>%"></div>
                   </div>
-                  <p><?=$lang['debug']['jvm_memory_solr'];?>: <?=$solr_status['jvm']['memory']['total'] - $solr_status['jvm']['memory']['free'];?> / <?=$solr_status['jvm']['memory']['total'];?>
+                  <p><?=$lang['debug']['jvm_memory_solr'];?>: <?=(int)$solr_status['jvm']['memory']['total'] - (int)$solr_status['jvm']['memory']['free'];?> / <?=$solr_status['jvm']['memory']['total'];?>
                     (<?=round($solr_status['jvm']['memory']['raw']['used%']);?>%)</p>
                   <hr>
                   <p><?=$lang['debug']['uptime'];?>: <?=round($solr_status['status']['dovecot-fts']['uptime'] / 1000 / 60 / 60);?>h</p>
diff --git a/data/web/develcow.de/index.html b/data/web/develcow.de/index.html
new file mode 100644
index 00000000..d72af314
--- /dev/null
+++ b/data/web/develcow.de/index.html
@@ -0,0 +1 @@
+asd
diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php
index 2cc1617a..65c7ab1d 100644
--- a/data/web/inc/functions.inc.php
+++ b/data/web/inc/functions.inc.php
@@ -126,8 +126,8 @@ function hash_password($password) {
   return $pw_hash;
 }
 function password_complexity($_action, $_data = null) {
-	global $redis;
-	global $lang;
+  global $redis;
+  global $lang;
   switch ($_action) {
     case 'edit':
       if ($_SESSION['mailcow_cc_role'] != "admin") {
@@ -253,7 +253,7 @@ function password_check($password1, $password2) {
 }
 function last_login($action, $username, $sasl_limit_days = 7) {
   global $pdo;
-	global $redis;
+  global $redis;
   $sasl_limit_days = intval($sasl_limit_days);
   switch ($action) {
     case 'get':
@@ -345,7 +345,7 @@ function last_login($action, $username, $sasl_limit_days = 7) {
       return true;
     break;
   }
-  
+
 }
 function flush_memcached() {
   try {
@@ -359,13 +359,13 @@ function flush_memcached() {
 }
 function sys_mail($_data) {
   if ($_SESSION['mailcow_cc_role'] != "admin") {
-		$_SESSION['return'][] =  array(
-			'type' => 'danger',
+    $_SESSION['return'][] =  array(
+      'type' => 'danger',
       'log' => array(__FUNCTION__),
-			'msg' => 'access_denied'
-		);
-		return false;
-	}
+      'msg' => 'access_denied'
+    );
+    return false;
+  }
   $excludes = $_data['mass_exclude'];
   $includes = $_data['mass_include'];
   $mailboxes = array();
@@ -374,28 +374,28 @@ function sys_mail($_data) {
   $mass_html = $_data['mass_html'];
   $mass_subject = $_data['mass_subject'];
   if (!filter_var($mass_from, FILTER_VALIDATE_EMAIL)) {
-		$_SESSION['return'][] =  array(
-			'type' => 'danger',
+    $_SESSION['return'][] =  array(
+      'type' => 'danger',
       'log' => array(__FUNCTION__),
-			'msg' => 'from_invalid'
-		);
-		return false;
+      'msg' => 'from_invalid'
+    );
+    return false;
   }
   if (empty($mass_subject)) {
-		$_SESSION['return'][] =  array(
-			'type' => 'danger',
+    $_SESSION['return'][] =  array(
+      'type' => 'danger',
       'log' => array(__FUNCTION__),
-			'msg' => 'subject_empty'
-		);
-		return false;
+      'msg' => 'subject_empty'
+    );
+    return false;
   }
   if (empty($mass_text)) {
-		$_SESSION['return'][] =  array(
-			'type' => 'danger',
+    $_SESSION['return'][] =  array(
+      'type' => 'danger',
       'log' => array(__FUNCTION__),
-			'msg' => 'text_empty'
-		);
-		return false;
+      'msg' => 'text_empty'
+    );
+    return false;
   }
   $domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains'));
   foreach ($domains as $domain) {
@@ -489,8 +489,14 @@ function logger($_data = false) {
     $task = substr(strtoupper(md5(uniqid(rand(), true))), 0, 6);
     foreach ($_data['return'] as $return) {
       $type = $return['type'];
-      $msg = json_encode($return['msg'], JSON_UNESCAPED_UNICODE);
-      $call = json_encode($return['log'], JSON_UNESCAPED_UNICODE);
+      $msg = null;
+      if (isset($return['msg'])) {
+        $msg = json_encode($return['msg'], JSON_UNESCAPED_UNICODE);
+      }
+      $call = null;
+      if (isset($return['log'])) {
+        $call = json_encode($return['log'], JSON_UNESCAPED_UNICODE);
+      }
       if (!empty($_SESSION["dual-login"]["username"])) {
         $user = $_SESSION["dual-login"]["username"] . ' => ' . $_SESSION['mailcow_cc_username'];
         $role = $_SESSION["dual-login"]["role"] . ' => ' . $_SESSION['mailcow_cc_role'];
@@ -527,16 +533,16 @@ function logger($_data = false) {
   }
 }
 function hasDomainAccess($username, $role, $domain) {
-	global $pdo;
-	if (!filter_var($username, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
-		return false;
-	}
-	if (empty($domain) || !is_valid_domain_name($domain)) {
-		return false;
-	}
-	if ($role != 'admin' && $role != 'domainadmin') {
-		return false;
-	}
+  global $pdo;
+  if (!filter_var($username, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
+    return false;
+  }
+  if (empty($domain) || !is_valid_domain_name($domain)) {
+    return false;
+  }
+  if ($role != 'admin' && $role != 'domainadmin') {
+    return false;
+  }
   if ($role == 'admin') {
     $stmt = $pdo->prepare("SELECT `domain` FROM `domain`
       WHERE `domain` = :domain");
@@ -563,49 +569,49 @@ function hasDomainAccess($username, $role, $domain) {
       return true;
     }
   }
-	return false;
+  return false;
 }
 function hasMailboxObjectAccess($username, $role, $object) {
-	global $pdo;
-	if (empty($username) || empty($role) || empty($object)) {
-		return false;
-	}
-	if (!filter_var(html_entity_decode(rawurldecode($username)), FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
-		return false;
-	}
-	if ($role != 'admin' && $role != 'domainadmin' && $role != 'user') {
-		return false;
-	}
-	if ($username == $object) {
-		return true;
-	}
+  global $pdo;
+  if (empty($username) || empty($role) || empty($object)) {
+    return false;
+  }
+  if (!filter_var(html_entity_decode(rawurldecode($username)), FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
+    return false;
+  }
+  if ($role != 'admin' && $role != 'domainadmin' && $role != 'user') {
+    return false;
+  }
+  if ($username == $object) {
+    return true;
+  }
   $stmt = $pdo->prepare("SELECT `domain` FROM `mailbox` WHERE `username` = :object");
   $stmt->execute(array(':object' => $object));
   $row = $stmt->fetch(PDO::FETCH_ASSOC);
   if (isset($row['domain']) && hasDomainAccess($username, $role, $row['domain'])) {
     return true;
   }
-	return false;
+  return false;
 }
 // does also verify mailboxes as a mailbox is a alias == goto
 function hasAliasObjectAccess($username, $role, $object) {
-	global $pdo;
-	if (empty($username) || empty($role) || empty($object)) {
-		return false;
-	}
-	if (!filter_var(html_entity_decode(rawurldecode($username)), FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
-		return false;
-	}
-	if ($role != 'admin' && $role != 'domainadmin' && $role != 'user') {
-		return false;
-	}
+  global $pdo;
+  if (empty($username) || empty($role) || empty($object)) {
+    return false;
+  }
+  if (!filter_var(html_entity_decode(rawurldecode($username)), FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $username))) {
+    return false;
+  }
+  if ($role != 'admin' && $role != 'domainadmin' && $role != 'user') {
+    return false;
+  }
   $stmt = $pdo->prepare("SELECT `domain` FROM `alias` WHERE `address` = :object");
   $stmt->execute(array(':object' => $object));
   $row = $stmt->fetch(PDO::FETCH_ASSOC);
   if (isset($row['domain']) && hasDomainAccess($username, $role, $row['domain'])) {
     return true;
   }
-	return false;
+  return false;
 }
 function pem_to_der($pem_key) {
   // Need to remove BEGIN/END PUBLIC KEY
@@ -615,9 +621,9 @@ function pem_to_der($pem_key) {
   return base64_decode(implode('', $lines));
 }
 function expand_ipv6($ip) {
-	$hex = unpack("H*hex", inet_pton($ip));
-	$ip = substr(preg_replace("/([A-f0-9]{4})/", "$1:", $hex['hex']), 0, -1);
-	return $ip;
+  $hex = unpack("H*hex", inet_pton($ip));
+  $ip = substr(preg_replace("/([A-f0-9]{4})/", "$1:", $hex['hex']), 0, -1);
+  return $ip;
 }
 function generate_tlsa_digest($hostname, $port, $starttls = null) {
   if (!is_valid_domain_name($hostname)) {
@@ -685,8 +691,10 @@ function alertbox_log_parser($_data) {
       // Get type
       $type = $return['type'];
       // If a lang[type][msg] string exists, use it as message
-      if (is_string($lang[$return['type']][$return['msg']])) {
-        $msg = $lang[$return['type']][$return['msg']];
+      if (isset($return['type']) && isset($return['msg']) && !is_array($return['msg'])) {
+        if (isset($lang[$return['type']][$return['msg']])) {
+          $msg = $lang[$return['type']][$return['msg']];
+        }
       }
       // If msg is an array, use first element as language string and run printf on it with remaining array elements
       elseif (is_array($return['msg'])) {
@@ -798,26 +806,26 @@ function verify_hash($hash, $password) {
   return false;
 }
 function check_login($user, $pass) {
-	global $pdo;
-	global $redis;
-	global $imap_server;
-	if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) {
+  global $pdo;
+  global $redis;
+  global $imap_server;
+  if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) {
     $_SESSION['return'][] =  array(
       'type' => 'danger',
       'log' => array(__FUNCTION__, $user, '*'),
       'msg' => 'malformed_username'
     );
-		return false;
-	}
-	$user = strtolower(trim($user));
-	$stmt = $pdo->prepare("SELECT `password` FROM `admin`
-			WHERE `superadmin` = '1'
-			AND `active` = '1'
-			AND `username` = :user");
-	$stmt->execute(array(':user' => $user));
-	$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
-	foreach ($rows as $row) {
-		if (verify_hash($row['password'], $pass)) {
+    return false;
+  }
+  $user = strtolower(trim($user));
+  $stmt = $pdo->prepare("SELECT `password` FROM `admin`
+      WHERE `superadmin` = '1'
+      AND `active` = '1'
+      AND `username` = :user");
+  $stmt->execute(array(':user' => $user));
+  $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+  foreach ($rows as $row) {
+    if (verify_hash($row['password'], $pass)) {
       if (get_tfa($user)['name'] != "none") {
         $_SESSION['pending_mailcow_cc_username'] = $user;
         $_SESSION['pending_mailcow_cc_role'] = "admin";
@@ -842,16 +850,16 @@ function check_login($user, $pass) {
         );
         return "admin";
       }
-		}
-	}
-	$stmt = $pdo->prepare("SELECT `password` FROM `admin`
-			WHERE `superadmin` = '0'
-			AND `active`='1'
-			AND `username` = :user");
-	$stmt->execute(array(':user' => $user));
-	$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
-	foreach ($rows as $row) {
-		if (verify_hash($row['password'], $pass) !== false) {
+    }
+  }
+  $stmt = $pdo->prepare("SELECT `password` FROM `admin`
+      WHERE `superadmin` = '0'
+      AND `active`='1'
+      AND `username` = :user");
+  $stmt->execute(array(':user' => $user));
+  $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+  foreach ($rows as $row) {
+    if (verify_hash($row['password'], $pass) !== false) {
       if (get_tfa($user)['name'] != "none") {
         $_SESSION['pending_mailcow_cc_username'] = $user;
         $_SESSION['pending_mailcow_cc_role'] = "domainadmin";
@@ -876,55 +884,55 @@ function check_login($user, $pass) {
         );
         return "domainadmin";
       }
-		}
-	}
-	$stmt = $pdo->prepare("SELECT `password` FROM `mailbox`
+    }
+  }
+  $stmt = $pdo->prepare("SELECT `password` FROM `mailbox`
       INNER JOIN domain on mailbox.domain = domain.domain
-			WHERE `kind` NOT REGEXP 'location|thing|group'
+      WHERE `kind` NOT REGEXP 'location|thing|group'
         AND `mailbox`.`active`='1'
         AND `domain`.`active`='1'
         AND `username` = :user");
-	$stmt->execute(array(':user' => $user));
-	$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
-	foreach ($rows as $row) {
-		if (verify_hash($row['password'], $pass) !== false) {
-			unset($_SESSION['ldelay']);
+  $stmt->execute(array(':user' => $user));
+  $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+  foreach ($rows as $row) {
+    if (verify_hash($row['password'], $pass) !== false) {
+      unset($_SESSION['ldelay']);
       $_SESSION['return'][] =  array(
         'type' => 'success',
         'log' => array(__FUNCTION__, $user, '*'),
         'msg' => array('logged_in_as', $user)
       );
-			return "user";
-		}
-	}
-	if (!isset($_SESSION['ldelay'])) {
-		$_SESSION['ldelay'] = "0";
+      return "user";
+    }
+  }
+  if (!isset($_SESSION['ldelay'])) {
+    $_SESSION['ldelay'] = "0";
     $redis->publish("F2B_CHANNEL", "mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']);
     error_log("mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']);
-	}
-	elseif (!isset($_SESSION['mailcow_cc_username'])) {
-		$_SESSION['ldelay'] = $_SESSION['ldelay']+0.5;
+  }
+  elseif (!isset($_SESSION['mailcow_cc_username'])) {
+    $_SESSION['ldelay'] = $_SESSION['ldelay']+0.5;
     $redis->publish("F2B_CHANNEL", "mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']);
-		error_log("mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']);
-	}
+    error_log("mailcow UI: Invalid password for " . $user . " by " . $_SERVER['REMOTE_ADDR']);
+  }
   $_SESSION['return'][] =  array(
     'type' => 'danger',
     'log' => array(__FUNCTION__, $user, '*'),
     'msg' => 'login_failed'
   );
-	sleep($_SESSION['ldelay']);
+  sleep($_SESSION['ldelay']);
   return false;
 }
 function formatBytes($size, $precision = 2) {
-	if(!is_numeric($size)) {
-		return "0";
-	}
-	$base = log($size, 1024);
-	$suffixes = array(' Byte', ' KiB', ' MiB', ' GiB', ' TiB');
-	if ($size == "0") {
-		return "0";
-	}
-	return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
+  if(!is_numeric($size)) {
+    return "0";
+  }
+  $base = log($size, 1024);
+  $suffixes = array(' Byte', ' KiB', ' MiB', ' GiB', ' TiB');
+  if ($size == "0") {
+    return "0";
+  }
+  return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
 }
 function update_sogo_static_view() {
   if (getenv('SKIP_SOGO') == "y") {
@@ -943,15 +951,15 @@ function update_sogo_static_view() {
   flush_memcached();
 }
 function edit_user_account($_data) {
-	global $lang;
-	global $pdo;
+  global $lang;
+  global $pdo;
   $_data_log = $_data;
   !isset($_data_log['user_new_pass']) ?: $_data_log['user_new_pass'] = '*';
   !isset($_data_log['user_new_pass2']) ?: $_data_log['user_new_pass2'] = '*';
   !isset($_data_log['user_old_pass']) ?: $_data_log['user_old_pass'] = '*';
   $username = $_SESSION['mailcow_cc_username'];
   $role = $_SESSION['mailcow_cc_role'];
-	$password_old = $_data['user_old_pass'];
+  $password_old = $_data['user_old_pass'];
   if (filter_var($username, FILTER_VALIDATE_EMAIL === false) || $role != 'user') {
     $_SESSION['return'][] =  array(
       'type' => 'danger',
@@ -960,11 +968,11 @@ function edit_user_account($_data) {
     );
     return false;
   }
-	$stmt = $pdo->prepare("SELECT `password` FROM `mailbox`
-			WHERE `kind` NOT REGEXP 'location|thing|group'
+  $stmt = $pdo->prepare("SELECT `password` FROM `mailbox`
+      WHERE `kind` NOT REGEXP 'location|thing|group'
         AND `username` = :user");
-	$stmt->execute(array(':user' => $username));
-	$row = $stmt->fetch(PDO::FETCH_ASSOC);
+  $stmt->execute(array(':user' => $username));
+  $row = $stmt->fetch(PDO::FETCH_ASSOC);
   if (!verify_hash($row['password'], $password_old)) {
     $_SESSION['return'][] =  array(
       'type' => 'danger',
@@ -973,9 +981,9 @@ function edit_user_account($_data) {
     );
     return false;
   }
-	if (!empty($_data['user_new_pass']) && !empty($_data['user_new_pass2'])) {
-		$password_new	= $_data['user_new_pass'];
-		$password_new2	= $_data['user_new_pass2'];
+  if (!empty($_data['user_new_pass']) && !empty($_data['user_new_pass2'])) {
+    $password_new	= $_data['user_new_pass'];
+    $password_new2	= $_data['user_new_pass2'];
     if (password_check($password_new, $password_new2) !== true) {
       return false;
     }
@@ -988,17 +996,17 @@ function edit_user_account($_data) {
       ':password_hashed' => $password_hashed,
       ':username' => $username
     ));
-	}
+  }
   update_sogo_static_view();
-	$_SESSION['return'][] =  array(
-		'type' => 'success',
+  $_SESSION['return'][] =  array(
+    'type' => 'success',
     'log' => array(__FUNCTION__, $_data_log),
-		'msg' => array('mailbox_modified', htmlspecialchars($username))
-	);
+    'msg' => array('mailbox_modified', htmlspecialchars($username))
+  );
 }
 function user_get_alias_details($username) {
-	global $pdo;
-	global $lang;
+  global $pdo;
+  global $lang;
   $data['direct_aliases'] = array();
   $data['shared_aliases'] = array();
   if ($_SESSION['mailcow_cc_role'] == "user") {
@@ -1073,19 +1081,19 @@ function user_get_alias_details($username) {
   return $data;
 }
 function is_valid_domain_name($domain_name) {
-	if (empty($domain_name)) {
-		return false;
-	}
-	$domain_name = idn_to_ascii($domain_name, 0, INTL_IDNA_VARIANT_UTS46);
-	return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name)
-		   && preg_match("/^.{1,253}$/", $domain_name)
-		   && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name));
+  if (empty($domain_name)) {
+    return false;
+  }
+  $domain_name = idn_to_ascii($domain_name, 0, INTL_IDNA_VARIANT_UTS46);
+  return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name)
+       && preg_match("/^.{1,253}$/", $domain_name)
+       && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name));
 }
 function set_tfa($_data) {
-	global $pdo;
-	global $yubi;
-	global $u2f;
-	global $tfa;
+  global $pdo;
+  global $yubi;
+  global $u2f;
+  global $tfa;
   $_data_log = $_data;
   !isset($_data_log['confirm_password']) ?: $_data_log['confirm_password'] = '*';
   $username = $_SESSION['mailcow_cc_username'];
@@ -1127,8 +1135,8 @@ function set_tfa($_data) {
       return false;
     }
   }
-	switch ($_data["tfa_method"]) {
-		case "yubi_otp":
+  switch ($_data["tfa_method"]) {
+    case "yubi_otp":
       $key_id = (!isset($_data["key_id"])) ? 'unidentified' : $_data["key_id"];
       $yubico_id = $_data['yubico_id'];
       $yubico_key = $_data['yubico_key'];
@@ -1141,55 +1149,55 @@ function set_tfa($_data) {
         );
         return false;
       }
-			if (!ctype_alnum($_data["otp_token"]) || strlen($_data["otp_token"]) != 44) {
-				$_SESSION['return'][] =  array(
-					'type' => 'danger',
+      if (!ctype_alnum($_data["otp_token"]) || strlen($_data["otp_token"]) != 44) {
+        $_SESSION['return'][] =  array(
+          'type' => 'danger',
           'log' => array(__FUNCTION__, $_data_log),
-					'msg' => 'tfa_token_invalid'
-				);
-				return false;
-			}
+          'msg' => 'tfa_token_invalid'
+        );
+        return false;
+      }
       $yauth = $yubi->verify($_data["otp_token"]);
       if (PEAR::isError($yauth)) {
-				$_SESSION['return'][] =  array(
-					'type' => 'danger',
+        $_SESSION['return'][] =  array(
+          'type' => 'danger',
           'log' => array(__FUNCTION__, $_data_log),
           'msg' => array('yotp_verification_failed', $yauth->getMessage())
-				);
-				return false;
+        );
+        return false;
       }
-			try {
+      try {
         // We could also do a modhex translation here
         $yubico_modhex_id = substr($_data["otp_token"], 0, 12);
         $stmt = $pdo->prepare("DELETE FROM `tfa`
           WHERE `username` = :username
             AND (`authmech` != 'yubi_otp')
             OR (`authmech` = 'yubi_otp' AND `secret` LIKE :modhex)");
-				$stmt->execute(array(':username' => $username, ':modhex' => '%' . $yubico_modhex_id));
-				$stmt = $pdo->prepare("INSERT INTO `tfa` (`key_id`, `username`, `authmech`, `active`, `secret`) VALUES
-					(:key_id, :username, 'yubi_otp', '1', :secret)");
-				$stmt->execute(array(':key_id' => $key_id, ':username' => $username, ':secret' => $yubico_id . ':' . $yubico_key . ':' . $yubico_modhex_id));
-			}
-			catch (PDOException $e) {
-				$_SESSION['return'][] =  array(
-					'type' => 'danger',
+        $stmt->execute(array(':username' => $username, ':modhex' => '%' . $yubico_modhex_id));
+        $stmt = $pdo->prepare("INSERT INTO `tfa` (`key_id`, `username`, `authmech`, `active`, `secret`) VALUES
+          (:key_id, :username, 'yubi_otp', '1', :secret)");
+        $stmt->execute(array(':key_id' => $key_id, ':username' => $username, ':secret' => $yubico_id . ':' . $yubico_key . ':' . $yubico_modhex_id));
+      }
+      catch (PDOException $e) {
+        $_SESSION['return'][] =  array(
+          'type' => 'danger',
           'log' => array(__FUNCTION__, $_data_log),
-					'msg' => array('mysql_error', $e)
-				);
-				return false;
-			}
-			$_SESSION['return'][] =  array(
-				'type' => 'success',
+          'msg' => array('mysql_error', $e)
+        );
+        return false;
+      }
+      $_SESSION['return'][] =  array(
+        'type' => 'success',
         'log' => array(__FUNCTION__, $_data_log),
-				'msg' => array('object_modified', htmlspecialchars($username))
-			);
-		break;
-		case "u2f":
+        'msg' => array('object_modified', htmlspecialchars($username))
+      );
+    break;
+    case "u2f":
       $key_id = (!isset($_data["key_id"])) ? 'unidentified' : $_data["key_id"];
       try {
         $reg = $u2f->doRegister(json_decode($_SESSION['regReq']), json_decode($_data['token']));
         $stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username AND `authmech` != 'u2f'");
-				$stmt->execute(array(':username' => $username));
+        $stmt->execute(array(':username' => $username));
         $stmt = $pdo->prepare("INSERT INTO `tfa` (`username`, `key_id`, `authmech`, `keyHandle`, `publicKey`, `certificate`, `counter`, `active`) VALUES (?, ?, 'u2f', ?, ?, ?, ?, '1')");
         $stmt->execute(array($username, $key_id, $reg->keyHandle, $reg->publicKey, $reg->certificate, $reg->counter));
         $_SESSION['return'][] =  array(
@@ -1208,8 +1216,8 @@ function set_tfa($_data) {
         $_SESSION['regReq'] = null;
         return false;
       }
-		break;
-		case "totp":
+    break;
+    case "totp":
       $key_id = (!isset($_data["key_id"])) ? 'unidentified' : $_data["key_id"];
       if ($tfa->verifyCode($_POST['totp_secret'], $_POST['totp_confirm_token']) === true) {
         $stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username");
@@ -1229,25 +1237,25 @@ function set_tfa($_data) {
           'msg' => 'totp_verification_failed'
         );
       }
-		break;
-		case "none":
+    break;
+    case "none":
       $stmt = $pdo->prepare("DELETE FROM `tfa` WHERE `username` = :username");
       $stmt->execute(array(':username' => $username));
-			$_SESSION['return'][] =  array(
-				'type' => 'success',
+      $_SESSION['return'][] =  array(
+        'type' => 'success',
         'log' => array(__FUNCTION__, $_data_log),
-				'msg' => array('object_modified', htmlspecialchars($username))
-			);
-		break;
-	}
+        'msg' => array('object_modified', htmlspecialchars($username))
+      );
+    break;
+  }
 }
 function fido2($_data) {
-	global $pdo;
+  global $pdo;
   $_data_log = $_data;
   // Not logging registration data, only actions
   // Silent errors for "get" requests
-	switch ($_data["action"]) {
-		case "register":
+  switch ($_data["action"]) {
+    case "register":
       $username = $_SESSION['mailcow_cc_username'];
       if (!isset($_SESSION['mailcow_cc_role']) || empty($username)) {
           $_SESSION['return'][] =  array(
@@ -1276,8 +1284,8 @@ function fido2($_data) {
         'log' => array(__FUNCTION__, $_data["action"]),
         'msg' => array('object_modified', $username)
       );
-		break;
-		case "get_user_cids":
+    break;
+    case "get_user_cids":
       // Used to exclude existing CredentialIds while registering
       $username = $_SESSION['mailcow_cc_username'];
       if (!isset($_SESSION['mailcow_cc_role']) || empty($username)) {
@@ -1290,8 +1298,8 @@ function fido2($_data) {
         $cids[] = $row['credentialId'];
       }
       return $cids;
-		break;
-		case "get_all_cids":
+    break;
+    case "get_all_cids":
       // Only needed when using fido2 with username
       $stmt = $pdo->query("SELECT `credentialId` FROM `fido2`");
       $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
@@ -1299,7 +1307,7 @@ function fido2($_data) {
         $cids[] = $row['credentialId'];
       }
       return $cids;
-		break;
+    break;
     case "get_by_b64cid":
       if (!isset($_data['cid']) || empty($_data['cid'])) {
         return false;
@@ -1315,8 +1323,8 @@ function fido2($_data) {
       $data['subject'] = $row['certificateSubject'];
       $data['cid'] = $row['cid'];
       return $data;
-		break;
-		case "get_friendly_names":
+    break;
+    case "get_friendly_names":
       $username = $_SESSION['mailcow_cc_username'];
       if (!isset($_SESSION['mailcow_cc_role']) || empty($username)) {
         return false;
@@ -1332,8 +1340,8 @@ function fido2($_data) {
         );
       }
       return $fns;
-		break;
-		case "unset_fido2_key":
+    break;
+    case "unset_fido2_key":
       $username = $_SESSION['mailcow_cc_username'];
       if (!isset($_SESSION['mailcow_cc_role']) || empty($username)) {
         $_SESSION['return'][] =  array(
@@ -1348,12 +1356,12 @@ function fido2($_data) {
         ':username' => $username,
         ':cid' => $_data['post_data']['unset_fido2_key']
       ));
-			$_SESSION['return'][] =  array(
-				'type' => 'success',
+      $_SESSION['return'][] =  array(
+        'type' => 'success',
         'log' => array(__FUNCTION__, $_data_log),
-				'msg' => array('object_modified', htmlspecialchars($username))
-			);
-		break;
+        'msg' => array('object_modified', htmlspecialchars($username))
+      );
+    break;
     case "edit_fn":
       $username = $_SESSION['mailcow_cc_username'];
       if (!isset($_SESSION['mailcow_cc_role']) || empty($username)) {
@@ -1370,13 +1378,13 @@ function fido2($_data) {
         ':friendlyName' => $_data['fido2_attrs']['fido2_fn'],
         ':cid' => $_data['fido2_attrs']['fido2_cid']
       ));
-			$_SESSION['return'][] =  array(
-				'type' => 'success',
+      $_SESSION['return'][] =  array(
+        'type' => 'success',
         'log' => array(__FUNCTION__, $_data_log),
-				'msg' => array('object_modified', htmlspecialchars($username))
-			);
-		break;
-	}
+        'msg' => array('object_modified', htmlspecialchars($username))
+      );
+    break;
+  }
 }
 function unset_tfa_key($_data) {
   // Can only unset own keys
@@ -1433,7 +1441,7 @@ function unset_tfa_key($_data) {
   }
 }
 function get_tfa($username = null) {
-	global $pdo;
+  global $pdo;
   if (isset($_SESSION['mailcow_cc_username'])) {
     $username = $_SESSION['mailcow_cc_username'];
   }
@@ -1445,76 +1453,83 @@ function get_tfa($username = null) {
   $stmt->execute(array(':username' => $username));
   $row = $stmt->fetch(PDO::FETCH_ASSOC);
 
-	switch ($row["authmech"]) {
-		case "yubi_otp":
-      $data['name'] = "yubi_otp";
-      $data['pretty'] = "Yubico OTP";
-      $stmt = $pdo->prepare("SELECT `id`, `key_id`, RIGHT(`secret`, 12) AS 'modhex' FROM `tfa` WHERE `authmech` = 'yubi_otp' AND `username` = :username");
-      $stmt->execute(array(
-        ':username' => $username,
-      ));
-      $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
-      while($row = array_shift($rows)) {
-        $data['additional'][] = $row;
-      }
-      return $data;
-    break;
-		case "u2f":
-      $data['name'] = "u2f";
-      $data['pretty'] = "Fido U2F";
-      $stmt = $pdo->prepare("SELECT `id`, `key_id` FROM `tfa` WHERE `authmech` = 'u2f' AND `username` = :username");
-      $stmt->execute(array(
-        ':username' => $username,
-      ));
-      $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
-      while($row = array_shift($rows)) {
-        $data['additional'][] = $row;
-      }
-      return $data;
-    break;
-		case "hotp":
-      $data['name'] = "hotp";
-      $data['pretty'] = "HMAC-based OTP";
-      return $data;
-		break;
- 		case "totp":
-      $data['name'] = "totp";
-      $data['pretty'] = "Time-based OTP";
-      $stmt = $pdo->prepare("SELECT `id`, `key_id`, `secret` FROM `tfa` WHERE `authmech` = 'totp' AND `username` = :username");
-      $stmt->execute(array(
-        ':username' => $username,
-      ));
-      $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
-      while($row = array_shift($rows)) {
-        $data['additional'][] = $row;
-      }
-      return $data;
+  if (isset($row["authmech"])) {
+    switch ($row["authmech"]) {
+      case "yubi_otp":
+        $data['name'] = "yubi_otp";
+        $data['pretty'] = "Yubico OTP";
+        $stmt = $pdo->prepare("SELECT `id`, `key_id`, RIGHT(`secret`, 12) AS 'modhex' FROM `tfa` WHERE `authmech` = 'yubi_otp' AND `username` = :username");
+        $stmt->execute(array(
+          ':username' => $username,
+        ));
+        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+        while($row = array_shift($rows)) {
+          $data['additional'][] = $row;
+        }
+        return $data;
       break;
-    default:
-      $data['name'] = 'none';
-      $data['pretty'] = "-";
-      return $data;
-    break;
-	}
+      case "u2f":
+        $data['name'] = "u2f";
+        $data['pretty'] = "Fido U2F";
+        $stmt = $pdo->prepare("SELECT `id`, `key_id` FROM `tfa` WHERE `authmech` = 'u2f' AND `username` = :username");
+        $stmt->execute(array(
+          ':username' => $username,
+        ));
+        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+        while($row = array_shift($rows)) {
+          $data['additional'][] = $row;
+        }
+        return $data;
+      break;
+      case "hotp":
+        $data['name'] = "hotp";
+        $data['pretty'] = "HMAC-based OTP";
+        return $data;
+      break;
+       case "totp":
+        $data['name'] = "totp";
+        $data['pretty'] = "Time-based OTP";
+        $stmt = $pdo->prepare("SELECT `id`, `key_id`, `secret` FROM `tfa` WHERE `authmech` = 'totp' AND `username` = :username");
+        $stmt->execute(array(
+          ':username' => $username,
+        ));
+        $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
+        while($row = array_shift($rows)) {
+          $data['additional'][] = $row;
+        }
+        return $data;
+        break;
+      default:
+        $data['name'] = 'none';
+        $data['pretty'] = "-";
+        return $data;
+      break;
+    }
+  }
+  else {
+    $data['name'] = 'none';
+    $data['pretty'] = "-";
+    return $data;
+  }
 }
 function verify_tfa_login($username, $token) {
-	global $pdo;
-	global $yubi;
-	global $u2f;
-	global $tfa;
+  global $pdo;
+  global $yubi;
+  global $u2f;
+  global $tfa;
   $stmt = $pdo->prepare("SELECT `authmech` FROM `tfa`
       WHERE `username` = :username AND `active` = '1'");
   $stmt->execute(array(':username' => $username));
   $row = $stmt->fetch(PDO::FETCH_ASSOC);
 
-	switch ($row["authmech"]) {
-		case "yubi_otp":
-			if (!ctype_alnum($token) || strlen($token) != 44) {
-				$_SESSION['return'][] =  array(
-					'type' => 'danger',
+  switch ($row["authmech"]) {
+    case "yubi_otp":
+      if (!ctype_alnum($token) || strlen($token) != 44) {
+        $_SESSION['return'][] =  array(
+          'type' => 'danger',
           'log' => array(__FUNCTION__, $username, '*'),
-					'msg' => array('yotp_verification_failed', 'token length error')
-				);
+          'msg' => array('yotp_verification_failed', 'token length error')
+        );
         return false;
       }
       $yubico_modhex_id = substr($token, 0, 12);
@@ -1529,20 +1544,20 @@ function verify_tfa_login($username, $token) {
       $yubi = new Auth_Yubico($yubico_auth[0], $yubico_auth[1]);
       $yauth = $yubi->verify($token);
       if (PEAR::isError($yauth)) {
-				$_SESSION['return'][] =  array(
-					'type' => 'danger',
+        $_SESSION['return'][] =  array(
+          'type' => 'danger',
           'log' => array(__FUNCTION__, $username, '*'),
-					'msg' => array('yotp_verification_failed', $yauth->getMessage())
-				);
-				return false;
+          'msg' => array('yotp_verification_failed', $yauth->getMessage())
+        );
+        return false;
       }
       else {
         $_SESSION['tfa_id'] = $row['id'];
-				$_SESSION['return'][] =  array(
-					'type' => 'success',
+        $_SESSION['return'][] =  array(
+          'type' => 'success',
           'log' => array(__FUNCTION__, $username, '*'),
-					'msg' => 'verified_yotp_login'
-				);
+          'msg' => 'verified_yotp_login'
+        );
         return true;
       }
       $_SESSION['return'][] =  array(
@@ -1627,31 +1642,34 @@ function verify_tfa_login($username, $token) {
     );
     return false;
   break;
-	}
+  }
   return false;
 }
 function admin_api($access, $action, $data = null) {
-	global $pdo;
-	if ($_SESSION['mailcow_cc_role'] != "admin") {
-		$_SESSION['return'][] =  array(
-			'type' => 'danger',
+  global $pdo;
+  if ($_SESSION['mailcow_cc_role'] != "admin") {
+    $_SESSION['return'][] =  array(
+      'type' => 'danger',
       'log' => array(__FUNCTION__),
-			'msg' => 'access_denied'
-		);
-		return false;
-	}
+      'msg' => 'access_denied'
+    );
+    return false;
+  }
   if ($access !== "ro" && $access !== "rw") {
-		$_SESSION['return'][] =  array(
-			'type' => 'danger',
+    $_SESSION['return'][] =  array(
+      'type' => 'danger',
       'log' => array(__FUNCTION__),
-			'msg' => 'invalid access type'
-		);
-		return false;
+      'msg' => 'invalid access type'
+    );
+    return false;
   }
   if ($action == "edit") {
     $active = (!empty($data['active'])) ? 1 : 0;
     $skip_ip_check = (isset($data['skip_ip_check'])) ? 1 : 0;
-    $allow_from = array_map('trim', preg_split( "/( |,|;|\n)/", $data['allow_from']));
+    $allow_from = array();
+    if (isset($data['allow_from'])) {
+      $allow_from = array_map('trim', preg_split( "/( |,|;|\n)/", $data['allow_from']));
+    }
     foreach ($allow_from as $key => $val) {
       if (empty($val)) {
         unset($allow_from[$key]);
@@ -1738,29 +1756,31 @@ function admin_api($access, $action, $data = null) {
   elseif ($action == "get") {
     $stmt = $pdo->query("SELECT * FROM `api` WHERE `access` = '" . $access . "'");
     $apidata = $stmt->fetch(PDO::FETCH_ASSOC);
-    $apidata['allow_from'] = str_replace(',', PHP_EOL, $apidata['allow_from']);
+    if ($apidata !== false) {
+      $apidata['allow_from'] = str_replace(',', PHP_EOL, $apidata['allow_from']);
+    }
     return $apidata;
   }
-	$_SESSION['return'][] =  array(
-		'type' => 'success',
+  $_SESSION['return'][] =  array(
+    'type' => 'success',
     'log' => array(__FUNCTION__, $data),
-		'msg' => 'admin_api_modified'
-	);
+    'msg' => 'admin_api_modified'
+  );
 }
 function license($action, $data = null) {
-	global $pdo;
-	global $redis;
-	global $lang;
-	if ($_SESSION['mailcow_cc_role'] != "admin") {
-		$_SESSION['return'][] =  array(
-			'type' => 'danger',
+  global $pdo;
+  global $redis;
+  global $lang;
+  if ($_SESSION['mailcow_cc_role'] != "admin") {
+    $_SESSION['return'][] =  array(
+      'type' => 'danger',
       'log' => array(__FUNCTION__),
-			'msg' => 'access_denied'
-		);
-		return false;
-	}
-	switch ($action) {
-		case "verify":
+      'msg' => 'access_denied'
+    );
+    return false;
+  }
+  switch ($action) {
+    case "verify":
       // Keep result until revalidate button is pressed or session expired
       $stmt = $pdo->query("SELECT `version` FROM `versions` WHERE `application` = 'GUID'");
       $versions = $stmt->fetch(PDO::FETCH_ASSOC);
@@ -1819,16 +1839,16 @@ function license($action, $data = null) {
   }
 }
 function rspamd_ui($action, $data = null) {
-	if ($_SESSION['mailcow_cc_role'] != "admin") {
-		$_SESSION['return'][] =  array(
-			'type' => 'danger',
+  if ($_SESSION['mailcow_cc_role'] != "admin") {
+    $_SESSION['return'][] =  array(
+      'type' => 'danger',
       'log' => array(__FUNCTION__),
-			'msg' => 'access_denied'
-		);
-		return false;
-	}
-	switch ($action) {
-		case "edit":
+      'msg' => 'access_denied'
+    );
+    return false;
+  }
+  switch ($action) {
+    case "edit":
       $rspamd_ui_pass = $data['rspamd_ui_pass'];
       $rspamd_ui_pass2 = $data['rspamd_ui_pass2'];
       if (empty($rspamd_ui_pass) || empty($rspamd_ui_pass2)) {
@@ -1904,11 +1924,11 @@ function get_logs($application, $lines = false) {
     $to = intval($to);
     if ($from < 1 || $to < $from) { return false; }
   }
-	global $redis;
-	global $pdo;
-	if ($_SESSION['mailcow_cc_role'] != "admin") {
-		return false;
-	}
+  global $redis;
+  global $pdo;
+  if ($_SESSION['mailcow_cc_role'] != "admin") {
+    return false;
+  }
   // SQL
   if ($application == "mailcow-ui") {
     if (isset($from) && isset($to)) {
diff --git a/data/web/inc/header.inc.php b/data/web/inc/header.inc.php
index 853c7924..d97a388b 100644
--- a/data/web/inc/header.inc.php
+++ b/data/web/inc/header.inc.php
@@ -110,7 +110,7 @@
             <?php foreach ($MAILCOW_APPS as $app) {
               if (getenv('SKIP_SOGO') == "y" && preg_match('/^\/SOGo/i', $app['link'])) { continue; }
             ?>
-              <li title="<?= htmlspecialchars($app['description']); ?>"><a href="<?= htmlspecialchars($app['link']); ?>"><?= htmlspecialchars($app['name']); ?></a></li>
+              <li title="<?=(isset($app['description'])) ? htmlspecialchars($app['description']) : '';?>"><a href="<?=(isset($app['link'])) ? htmlspecialchars($app['link']) : '';?>"><?=(isset($app['name'])) ? htmlspecialchars($app['name']) : '';?></a></li>
             <?php
             }
             $app_links = customize('get', 'app_links');
diff --git a/data/web/inc/lib/composer.json b/data/web/inc/lib/composer.json
index 9ef86fca..e7e6b682 100644
--- a/data/web/inc/lib/composer.json
+++ b/data/web/inc/lib/composer.json
@@ -3,7 +3,7 @@
         "robthree/twofactorauth": "^1.6",
         "yubico/u2flib-server": "^1.0",
         "phpmailer/phpmailer": "^6.1",
-        "php-mime-mail-parser/php-mime-mail-parser": "^5.0.5",
+        "php-mime-mail-parser/php-mime-mail-parser": "^7",
         "soundasleep/html2text": "^0.5.0",
         "ddeboer/imap": "^1.5",
         "matthiasmullie/minify": "^1.3",
diff --git a/data/web/inc/lib/composer.lock b/data/web/inc/lib/composer.lock
index 035202d8..e2633cc0 100644
--- a/data/web/inc/lib/composer.lock
+++ b/data/web/inc/lib/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "ffadb60e56b9e032d9a1777a5bf26477",
+    "content-hash": "50acd623ff29bb513cd29819f4537aa0",
     "packages": [
         {
             "name": "bshaffer/oauth2-server-php",
@@ -144,16 +144,16 @@
         },
         {
             "name": "directorytree/ldaprecord",
-            "version": "v2.5.0",
+            "version": "v2.6.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/DirectoryTree/LdapRecord.git",
-                "reference": "ff7a92615fdc3f8b7f3d347c2847ce7ce06db287"
+                "reference": "5c93ec6d1ef458290825a8b0a148946dce7c1e7a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/ff7a92615fdc3f8b7f3d347c2847ce7ce06db287",
-                "reference": "ff7a92615fdc3f8b7f3d347c2847ce7ce06db287",
+                "url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/5c93ec6d1ef458290825a8b0a148946dce7c1e7a",
+                "reference": "5c93ec6d1ef458290825a8b0a148946dce7c1e7a",
                 "shasum": ""
             },
             "require": {
@@ -213,20 +213,20 @@
                     "type": "github"
                 }
             ],
-            "time": "2021-06-06T18:51:41+00:00"
+            "time": "2021-08-05T21:52:43+00:00"
         },
         {
             "name": "illuminate/contracts",
-            "version": "v8.48.0",
+            "version": "v8.53.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/contracts.git",
-                "reference": "199fcedc161ba4a0b83feaddc4629f395dbf1641"
+                "reference": "504a34286a1b4c5421c43087d6bd4e176138f6fb"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/illuminate/contracts/zipball/199fcedc161ba4a0b83feaddc4629f395dbf1641",
-                "reference": "199fcedc161ba4a0b83feaddc4629f395dbf1641",
+                "url": "https://api.github.com/repos/illuminate/contracts/zipball/504a34286a1b4c5421c43087d6bd4e176138f6fb",
+                "reference": "504a34286a1b4c5421c43087d6bd4e176138f6fb",
                 "shasum": ""
             },
             "require": {
@@ -261,7 +261,7 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2021-06-01T14:53:38+00:00"
+            "time": "2021-08-03T14:03:47+00:00"
         },
         {
             "name": "matthiasmullie/minify",
@@ -446,22 +446,23 @@
         },
         {
             "name": "nesbot/carbon",
-            "version": "2.49.0",
+            "version": "2.51.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/briannesbitt/Carbon.git",
-                "reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee"
+                "reference": "8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/93d9db91c0235c486875d22f1e08b50bdf3e6eee",
-                "reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee",
+                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922",
+                "reference": "8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922",
                 "shasum": ""
             },
             "require": {
                 "ext-json": "*",
                 "php": "^7.1.8 || ^8.0",
                 "symfony/polyfill-mbstring": "^1.0",
+                "symfony/polyfill-php80": "^1.16",
                 "symfony/translation": "^3.4 || ^4.0 || ^5.0"
             },
             "require-dev": {
@@ -480,8 +481,8 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.x-dev",
-                    "dev-3.x": "3.x-dev"
+                    "dev-3.x": "3.x-dev",
+                    "dev-master": "2.x-dev"
                 },
                 "laravel": {
                     "providers": [
@@ -507,15 +508,15 @@
                 {
                     "name": "Brian Nesbitt",
                     "email": "[email protected]",
-                    "homepage": "http://nesbot.com"
+                    "homepage": "https://markido.com"
                 },
                 {
                     "name": "kylekatarnls",
-                    "homepage": "http://github.com/kylekatarnls"
+                    "homepage": "https://github.com/kylekatarnls"
                 }
             ],
             "description": "An API extension for DateTime that supports 281 different languages.",
-            "homepage": "http://carbon.nesbot.com",
+            "homepage": "https://carbon.nesbot.com",
             "keywords": [
                 "date",
                 "datetime",
@@ -535,7 +536,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-06-02T07:31:40+00:00"
+            "time": "2021-07-28T13:16:28+00:00"
         },
         {
             "name": "paragonie/random_compat",
@@ -589,31 +590,30 @@
         },
         {
             "name": "php-mime-mail-parser/php-mime-mail-parser",
-            "version": "5.0.5",
+            "version": "7.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/php-mime-mail-parser/php-mime-mail-parser.git",
-                "reference": "27983433aabeccee832573c3c56e6a4855e57745"
+                "reference": "9d09a017f3f103fec8456211a4a538b80e0eca0d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/php-mime-mail-parser/php-mime-mail-parser/zipball/27983433aabeccee832573c3c56e6a4855e57745",
-                "reference": "27983433aabeccee832573c3c56e6a4855e57745",
+                "url": "https://api.github.com/repos/php-mime-mail-parser/php-mime-mail-parser/zipball/9d09a017f3f103fec8456211a4a538b80e0eca0d",
+                "reference": "9d09a017f3f103fec8456211a4a538b80e0eca0d",
                 "shasum": ""
             },
             "require": {
                 "ext-mailparse": "*",
-                "php": "^7.1"
+                "php": "^7.2|^8.0"
             },
             "replace": {
                 "exorus/php-mime-mail-parser": "*",
                 "messaged/php-mime-mail-parser": "*"
             },
             "require-dev": {
-                "php-coveralls/php-coveralls": "^2.1",
-                "phpunit/php-token-stream": "^3.0",
-                "phpunit/phpunit": "^7.0",
-                "squizlabs/php_codesniffer": "^3.4"
+                "php-coveralls/php-coveralls": "^2.2",
+                "phpunit/phpunit": "^8.0",
+                "squizlabs/php_codesniffer": "^3.5"
             },
             "type": "library",
             "autoload": {
@@ -657,7 +657,7 @@
                     "role": "Developer"
                 }
             ],
-            "description": "A fully tested email parser for PHP 7.1+ (mailparse extension wrapper).",
+            "description": "A fully tested email parser for PHP 7.2+ (mailparse extension wrapper).",
             "homepage": "https://github.com/php-mime-mail-parser/php-mime-mail-parser",
             "keywords": [
                 "MimeMailParser",
@@ -669,9 +669,15 @@
             ],
             "support": {
                 "issues": "https://github.com/php-mime-mail-parser/php-mime-mail-parser/issues",
-                "source": "https://github.com/php-mime-mail-parser/php-mime-mail-parser/tree/master"
+                "source": "https://github.com/php-mime-mail-parser/php-mime-mail-parser/tree/7.0.0"
             },
-            "time": "2019-09-23T11:57:58+00:00"
+            "funding": [
+                {
+                    "url": "https://github.com/eXorus",
+                    "type": "github"
+                }
+            ],
+            "time": "2021-02-25T17:21:57+00:00"
         },
         {
             "name": "phpmailer/phpmailer",
@@ -1092,16 +1098,16 @@
         },
         {
             "name": "symfony/polyfill-mbstring",
-            "version": "v1.23.0",
+            "version": "v1.23.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-mbstring.git",
-                "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1"
+                "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
-                "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
+                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6",
+                "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6",
                 "shasum": ""
             },
             "require": {
@@ -1152,7 +1158,7 @@
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0"
+                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1"
             },
             "funding": [
                 {
@@ -1168,20 +1174,20 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-05-27T09:27:20+00:00"
+            "time": "2021-05-27T12:26:48+00:00"
         },
         {
             "name": "symfony/polyfill-php80",
-            "version": "v1.23.0",
+            "version": "v1.23.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-php80.git",
-                "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0"
+                "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0",
-                "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0",
+                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be",
+                "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be",
                 "shasum": ""
             },
             "require": {
@@ -1235,7 +1241,7 @@
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0"
+                "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1"
             },
             "funding": [
                 {
@@ -1251,27 +1257,27 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-02-19T12:13:01+00:00"
+            "time": "2021-07-28T13:41:28+00:00"
         },
         {
             "name": "symfony/translation",
-            "version": "v5.3.2",
+            "version": "v5.3.4",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/translation.git",
-                "reference": "7e2603bcc598e14804c4d2359d8dc4ee3c40391b"
+                "reference": "d89ad7292932c2699cbe4af98d72c5c6bbc504c1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/translation/zipball/7e2603bcc598e14804c4d2359d8dc4ee3c40391b",
-                "reference": "7e2603bcc598e14804c4d2359d8dc4ee3c40391b",
+                "url": "https://api.github.com/repos/symfony/translation/zipball/d89ad7292932c2699cbe4af98d72c5c6bbc504c1",
+                "reference": "d89ad7292932c2699cbe4af98d72c5c6bbc504c1",
                 "shasum": ""
             },
             "require": {
                 "php": ">=7.2.5",
                 "symfony/deprecation-contracts": "^2.1",
                 "symfony/polyfill-mbstring": "~1.0",
-                "symfony/polyfill-php80": "^1.15",
+                "symfony/polyfill-php80": "^1.16",
                 "symfony/translation-contracts": "^2.3"
             },
             "conflict": {
@@ -1285,7 +1291,7 @@
                 "symfony/translation-implementation": "2.3"
             },
             "require-dev": {
-                "psr/log": "~1.0",
+                "psr/log": "^1|^2|^3",
                 "symfony/config": "^4.4|^5.0",
                 "symfony/console": "^4.4|^5.0",
                 "symfony/dependency-injection": "^5.0",
@@ -1330,7 +1336,7 @@
             "description": "Provides tools to internationalize your application",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/translation/tree/v5.3.2"
+                "source": "https://github.com/symfony/translation/tree/v5.3.4"
             },
             "funding": [
                 {
@@ -1346,7 +1352,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-06-06T09:51:56+00:00"
+            "time": "2021-07-25T09:39:16+00:00"
         },
         {
             "name": "symfony/translation-contracts",
@@ -1428,22 +1434,22 @@
         },
         {
             "name": "symfony/var-dumper",
-            "version": "v5.3.2",
+            "version": "v5.3.6",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/var-dumper.git",
-                "reference": "905a22c68b292ffb6f20d7636c36b220d1fba5ae"
+                "reference": "3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/905a22c68b292ffb6f20d7636c36b220d1fba5ae",
-                "reference": "905a22c68b292ffb6f20d7636c36b220d1fba5ae",
+                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0",
+                "reference": "3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0",
                 "shasum": ""
             },
             "require": {
                 "php": ">=7.2.5",
                 "symfony/polyfill-mbstring": "~1.0",
-                "symfony/polyfill-php80": "^1.15"
+                "symfony/polyfill-php80": "^1.16"
             },
             "conflict": {
                 "phpunit/phpunit": "<5.4.3",
@@ -1496,7 +1502,7 @@
                 "dump"
             ],
             "support": {
-                "source": "https://github.com/symfony/var-dumper/tree/v5.3.2"
+                "source": "https://github.com/symfony/var-dumper/tree/v5.3.6"
             },
             "funding": [
                 {
@@ -1512,7 +1518,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2021-06-06T09:51:56+00:00"
+            "time": "2021-07-27T01:56:02+00:00"
         },
         {
             "name": "tightenco/collect",
@@ -1618,5 +1624,5 @@
     "prefer-lowest": false,
     "platform": [],
     "platform-dev": [],
-    "plugin-api-version": "2.0.0"
+    "plugin-api-version": "2.1.0"
 }
diff --git a/data/web/inc/lib/vendor/composer/ClassLoader.php b/data/web/inc/lib/vendor/composer/ClassLoader.php
index 247294d6..6d0c3f2d 100644
--- a/data/web/inc/lib/vendor/composer/ClassLoader.php
+++ b/data/web/inc/lib/vendor/composer/ClassLoader.php
@@ -338,7 +338,7 @@ class ClassLoader
      * Loads the given class or interface.
      *
      * @param  string    $class The name of the class
-     * @return bool|null True if loaded, null otherwise
+     * @return true|null True if loaded, null otherwise
      */
     public function loadClass($class)
     {
@@ -347,6 +347,8 @@ class ClassLoader
 
             return true;
         }
+
+        return null;
     }
 
     /**
diff --git a/data/web/inc/lib/vendor/composer/InstalledVersions.php b/data/web/inc/lib/vendor/composer/InstalledVersions.php
index 65906e7a..b3a4e161 100644
--- a/data/web/inc/lib/vendor/composer/InstalledVersions.php
+++ b/data/web/inc/lib/vendor/composer/InstalledVersions.php
@@ -1,536 +1,337 @@
 <?php
 
-
-
-
-
-
-
-
-
-
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <[email protected]>
+ *     Jordi Boggiano <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
 
 namespace Composer;
 
 use Composer\Autoload\ClassLoader;
 use Composer\Semver\VersionParser;
 
-
-
-
-
-
-
-
+/**
+ * This class is copied in every Composer installed project and available to all
+ *
+ * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
+ *
+ * To require it's presence, you can require `composer-runtime-api ^2.0`
+ */
 class InstalledVersions
 {
-private static $installed = array (
-  'root' => 
-  array (
-    'pretty_version' => '1.0.0+no-version-set',
-    'version' => '1.0.0.0',
-    'aliases' => 
-    array (
-    ),
-    'reference' => NULL,
-    'name' => '__root__',
-  ),
-  'versions' => 
-  array (
-    '__root__' => 
-    array (
-      'pretty_version' => '1.0.0+no-version-set',
-      'version' => '1.0.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => NULL,
-    ),
-    'bshaffer/oauth2-server-php' => 
-    array (
-      'pretty_version' => 'v1.11.1',
-      'version' => '1.11.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '5a0c8000d4763b276919e2106f54eddda6bc50fa',
-    ),
-    'ddeboer/imap' => 
-    array (
-      'pretty_version' => '1.12.1',
-      'version' => '1.12.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'dbed05ca67b93509345a820b2859de10c48948fb',
-    ),
-    'directorytree/ldaprecord' => 
-    array (
-      'pretty_version' => 'v2.5.0',
-      'version' => '2.5.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'ff7a92615fdc3f8b7f3d347c2847ce7ce06db287',
-    ),
-    'exorus/php-mime-mail-parser' => 
-    array (
-      'replaced' => 
-      array (
-        0 => '*',
-      ),
-    ),
-    'illuminate/contracts' => 
-    array (
-      'pretty_version' => 'v8.48.0',
-      'version' => '8.48.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '199fcedc161ba4a0b83feaddc4629f395dbf1641',
-    ),
-    'matthiasmullie/minify' => 
-    array (
-      'pretty_version' => '1.3.66',
-      'version' => '1.3.66.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '45fd3b0f1dfa2c965857c6d4a470bea52adc31a6',
-    ),
-    'matthiasmullie/path-converter' => 
-    array (
-      'pretty_version' => '1.1.3',
-      'version' => '1.1.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'e7d13b2c7e2f2268e1424aaed02085518afa02d9',
-    ),
-    'messaged/php-mime-mail-parser' => 
-    array (
-      'replaced' => 
-      array (
-        0 => '*',
-      ),
-    ),
-    'mustangostang/spyc' => 
-    array (
-      'pretty_version' => '0.6.3',
-      'version' => '0.6.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '4627c838b16550b666d15aeae1e5289dd5b77da0',
-    ),
-    'nesbot/carbon' => 
-    array (
-      'pretty_version' => '2.49.0',
-      'version' => '2.49.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '93d9db91c0235c486875d22f1e08b50bdf3e6eee',
-    ),
-    'paragonie/random_compat' => 
-    array (
-      'pretty_version' => 'v9.99.100',
-      'version' => '9.99.100.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
-    ),
-    'php-mime-mail-parser/php-mime-mail-parser' => 
-    array (
-      'pretty_version' => '5.0.5',
-      'version' => '5.0.5.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '27983433aabeccee832573c3c56e6a4855e57745',
-    ),
-    'phpmailer/phpmailer' => 
-    array (
-      'pretty_version' => 'v6.5.0',
-      'version' => '6.5.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a5b5c43e50b7fba655f793ad27303cd74c57363c',
-    ),
-    'psr/container' => 
-    array (
-      'pretty_version' => '1.1.1',
-      'version' => '1.1.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf',
-    ),
-    'psr/log' => 
-    array (
-      'pretty_version' => '1.1.4',
-      'version' => '1.1.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
-    ),
-    'psr/simple-cache' => 
-    array (
-      'pretty_version' => '1.0.1',
-      'version' => '1.0.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
-    ),
-    'robthree/twofactorauth' => 
-    array (
-      'pretty_version' => '1.8.0',
-      'version' => '1.8.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '30a38627ae1e7c9399dae67e265063cd6ec5276c',
-    ),
-    'soundasleep/html2text' => 
-    array (
-      'pretty_version' => '0.5.0',
-      'version' => '0.5.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'cdb89f6ffa2c4cc78f8ed9ea6ee0594a9133ccad',
-    ),
-    'symfony/deprecation-contracts' => 
-    array (
-      'pretty_version' => 'v2.4.0',
-      'version' => '2.4.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '5f38c8804a9e97d23e0c8d63341088cd8a22d627',
-    ),
-    'symfony/polyfill-mbstring' => 
-    array (
-      'pretty_version' => 'v1.23.0',
-      'version' => '1.23.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '2df51500adbaebdc4c38dea4c89a2e131c45c8a1',
-    ),
-    'symfony/polyfill-php80' => 
-    array (
-      'pretty_version' => 'v1.23.0',
-      'version' => '1.23.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'eca0bf41ed421bed1b57c4958bab16aa86b757d0',
-    ),
-    'symfony/translation' => 
-    array (
-      'pretty_version' => 'v5.3.2',
-      'version' => '5.3.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '7e2603bcc598e14804c4d2359d8dc4ee3c40391b',
-    ),
-    'symfony/translation-contracts' => 
-    array (
-      'pretty_version' => 'v2.4.0',
-      'version' => '2.4.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '95c812666f3e91db75385749fe219c5e494c7f95',
-    ),
-    'symfony/translation-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '2.3',
-      ),
-    ),
-    'symfony/var-dumper' => 
-    array (
-      'pretty_version' => 'v5.3.2',
-      'version' => '5.3.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '905a22c68b292ffb6f20d7636c36b220d1fba5ae',
-    ),
-    'tightenco/collect' => 
-    array (
-      'pretty_version' => 'v8.34.0',
-      'version' => '8.34.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'b069783ab0c547bb894ebcf8e7f6024bb401f9d2',
-    ),
-    'yubico/u2flib-server' => 
-    array (
-      'pretty_version' => '1.0.2',
-      'version' => '1.0.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '55d813acf68212ad2cadecde07551600d6971939',
-    ),
-  ),
-);
-private static $canGetVendors;
-private static $installedByVendor = array();
-
-
-
-
-
-
-
-public static function getInstalledPackages()
-{
-$packages = array();
-foreach (self::getInstalled() as $installed) {
-$packages[] = array_keys($installed['versions']);
-}
-
-if (1 === \count($packages)) {
-return $packages[0];
-}
-
-return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
-}
-
-
-
-
-
-
-
-
-
-public static function isInstalled($packageName)
-{
-foreach (self::getInstalled() as $installed) {
-if (isset($installed['versions'][$packageName])) {
-return true;
-}
-}
-
-return false;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-public static function satisfies(VersionParser $parser, $packageName, $constraint)
-{
-$constraint = $parser->parseConstraints($constraint);
-$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
-
-return $provided->matches($constraint);
-}
-
-
-
-
-
-
-
-
-
-
-public static function getVersionRanges($packageName)
-{
-foreach (self::getInstalled() as $installed) {
-if (!isset($installed['versions'][$packageName])) {
-continue;
-}
-
-$ranges = array();
-if (isset($installed['versions'][$packageName]['pretty_version'])) {
-$ranges[] = $installed['versions'][$packageName]['pretty_version'];
-}
-if (array_key_exists('aliases', $installed['versions'][$packageName])) {
-$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
-}
-if (array_key_exists('replaced', $installed['versions'][$packageName])) {
-$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
-}
-if (array_key_exists('provided', $installed['versions'][$packageName])) {
-$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
-}
-
-return implode(' || ', $ranges);
-}
-
-throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
-}
-
-
-
-
-
-public static function getVersion($packageName)
-{
-foreach (self::getInstalled() as $installed) {
-if (!isset($installed['versions'][$packageName])) {
-continue;
-}
-
-if (!isset($installed['versions'][$packageName]['version'])) {
-return null;
-}
-
-return $installed['versions'][$packageName]['version'];
-}
-
-throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
-}
-
-
-
-
-
-public static function getPrettyVersion($packageName)
-{
-foreach (self::getInstalled() as $installed) {
-if (!isset($installed['versions'][$packageName])) {
-continue;
-}
-
-if (!isset($installed['versions'][$packageName]['pretty_version'])) {
-return null;
-}
-
-return $installed['versions'][$packageName]['pretty_version'];
-}
-
-throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
-}
-
-
-
-
-
-public static function getReference($packageName)
-{
-foreach (self::getInstalled() as $installed) {
-if (!isset($installed['versions'][$packageName])) {
-continue;
-}
-
-if (!isset($installed['versions'][$packageName]['reference'])) {
-return null;
-}
-
-return $installed['versions'][$packageName]['reference'];
-}
-
-throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
-}
-
-
-
-
-
-public static function getRootPackage()
-{
-$installed = self::getInstalled();
-
-return $installed[0]['root'];
-}
-
-
-
-
-
-
-
-
-public static function getRawData()
-{
-@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
-
-return self::$installed;
-}
-
-
-
-
-
-
-
-public static function getAllRawData()
-{
-return self::getInstalled();
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-public static function reload($data)
-{
-self::$installed = $data;
-self::$installedByVendor = array();
-}
-
-
-
-
-
-private static function getInstalled()
-{
-if (null === self::$canGetVendors) {
-self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
-}
-
-$installed = array();
-
-if (self::$canGetVendors) {
-foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
-if (isset(self::$installedByVendor[$vendorDir])) {
-$installed[] = self::$installedByVendor[$vendorDir];
-} elseif (is_file($vendorDir.'/composer/installed.php')) {
-$installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
-}
-}
-}
-
-$installed[] = self::$installed;
-
-return $installed;
-}
+    private static $installed;
+    private static $canGetVendors;
+    private static $installedByVendor = array();
+
+    /**
+     * Returns a list of all package names which are present, either by being installed, replaced or provided
+     *
+     * @return string[]
+     * @psalm-return list<string>
+     */
+    public static function getInstalledPackages()
+    {
+        $packages = array();
+        foreach (self::getInstalled() as $installed) {
+            $packages[] = array_keys($installed['versions']);
+        }
+
+        if (1 === \count($packages)) {
+            return $packages[0];
+        }
+
+        return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
+    }
+
+    /**
+     * Returns a list of all package names with a specific type e.g. 'library'
+     *
+     * @param  string   $type
+     * @return string[]
+     * @psalm-return list<string>
+     */
+    public static function getInstalledPackagesByType($type)
+    {
+        $packagesByType = array();
+
+        foreach (self::getInstalled() as $installed) {
+            foreach ($installed['versions'] as $name => $package) {
+                if (isset($package['type']) && $package['type'] === $type) {
+                    $packagesByType[] = $name;
+                }
+            }
+        }
+
+        return $packagesByType;
+    }
+
+    /**
+     * Checks whether the given package is installed
+     *
+     * This also returns true if the package name is provided or replaced by another package
+     *
+     * @param  string $packageName
+     * @param  bool   $includeDevRequirements
+     * @return bool
+     */
+    public static function isInstalled($packageName, $includeDevRequirements = true)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (isset($installed['versions'][$packageName])) {
+                return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Checks whether the given package satisfies a version constraint
+     *
+     * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
+     *
+     *   Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
+     *
+     * @param  VersionParser $parser      Install composer/semver to have access to this class and functionality
+     * @param  string        $packageName
+     * @param  string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
+     * @return bool
+     */
+    public static function satisfies(VersionParser $parser, $packageName, $constraint)
+    {
+        $constraint = $parser->parseConstraints($constraint);
+        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
+
+        return $provided->matches($constraint);
+    }
+
+    /**
+     * Returns a version constraint representing all the range(s) which are installed for a given package
+     *
+     * It is easier to use this via isInstalled() with the $constraint argument if you need to check
+     * whether a given version of a package is installed, and not just whether it exists
+     *
+     * @param  string $packageName
+     * @return string Version constraint usable with composer/semver
+     */
+    public static function getVersionRanges($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            $ranges = array();
+            if (isset($installed['versions'][$packageName]['pretty_version'])) {
+                $ranges[] = $installed['versions'][$packageName]['pretty_version'];
+            }
+            if (array_key_exists('aliases', $installed['versions'][$packageName])) {
+                $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
+            }
+            if (array_key_exists('replaced', $installed['versions'][$packageName])) {
+                $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
+            }
+            if (array_key_exists('provided', $installed['versions'][$packageName])) {
+                $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
+            }
+
+            return implode(' || ', $ranges);
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+     */
+    public static function getVersion($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            if (!isset($installed['versions'][$packageName]['version'])) {
+                return null;
+            }
+
+            return $installed['versions'][$packageName]['version'];
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
+     */
+    public static function getPrettyVersion($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            if (!isset($installed['versions'][$packageName]['pretty_version'])) {
+                return null;
+            }
+
+            return $installed['versions'][$packageName]['pretty_version'];
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
+     */
+    public static function getReference($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            if (!isset($installed['versions'][$packageName]['reference'])) {
+                return null;
+            }
+
+            return $installed['versions'][$packageName]['reference'];
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @param  string      $packageName
+     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
+     */
+    public static function getInstallPath($packageName)
+    {
+        foreach (self::getInstalled() as $installed) {
+            if (!isset($installed['versions'][$packageName])) {
+                continue;
+            }
+
+            return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
+        }
+
+        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
+    }
+
+    /**
+     * @return array
+     * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}
+     */
+    public static function getRootPackage()
+    {
+        $installed = self::getInstalled();
+
+        return $installed[0]['root'];
+    }
+
+    /**
+     * Returns the raw installed.php data for custom implementations
+     *
+     * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
+     * @return array[]
+     * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}
+     */
+    public static function getRawData()
+    {
+        @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
+
+        if (null === self::$installed) {
+            // only require the installed.php file if this file is loaded from its dumped location,
+            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+            if (substr(__DIR__, -8, 1) !== 'C') {
+                self::$installed = include __DIR__ . '/installed.php';
+            } else {
+                self::$installed = array();
+            }
+        }
+
+        return self::$installed;
+    }
+
+    /**
+     * Returns the raw data of all installed.php which are currently loaded for custom implementations
+     *
+     * @return array[]
+     * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}>
+     */
+    public static function getAllRawData()
+    {
+        return self::getInstalled();
+    }
+
+    /**
+     * Lets you reload the static array from another file
+     *
+     * This is only useful for complex integrations in which a project needs to use
+     * this class but then also needs to execute another project's autoloader in process,
+     * and wants to ensure both projects have access to their version of installed.php.
+     *
+     * A typical case would be PHPUnit, where it would need to make sure it reads all
+     * the data it needs from this class, then call reload() with
+     * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
+     * the project in which it runs can then also use this class safely, without
+     * interference between PHPUnit's dependencies and the project's dependencies.
+     *
+     * @param  array[] $data A vendor/composer/installed.php data set
+     * @return void
+     *
+     * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>} $data
+     */
+    public static function reload($data)
+    {
+        self::$installed = $data;
+        self::$installedByVendor = array();
+    }
+
+    /**
+     * @return array[]
+     * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}>
+     */
+    private static function getInstalled()
+    {
+        if (null === self::$canGetVendors) {
+            self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
+        }
+
+        $installed = array();
+
+        if (self::$canGetVendors) {
+            foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
+                if (isset(self::$installedByVendor[$vendorDir])) {
+                    $installed[] = self::$installedByVendor[$vendorDir];
+                } elseif (is_file($vendorDir.'/composer/installed.php')) {
+                    $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
+                    if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
+                        self::$installed = $installed[count($installed) - 1];
+                    }
+                }
+            }
+        }
+
+        if (null === self::$installed) {
+            // only require the installed.php file if this file is loaded from its dumped location,
+            // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
+            if (substr(__DIR__, -8, 1) !== 'C') {
+                self::$installed = require __DIR__ . '/installed.php';
+            } else {
+                self::$installed = array();
+            }
+        }
+        $installed[] = self::$installed;
+
+        return $installed;
+    }
 }
diff --git a/data/web/inc/lib/vendor/composer/autoload_files.php b/data/web/inc/lib/vendor/composer/autoload_files.php
index bb6e4f97..fac18c7f 100644
--- a/data/web/inc/lib/vendor/composer/autoload_files.php
+++ b/data/web/inc/lib/vendor/composer/autoload_files.php
@@ -6,8 +6,8 @@ $vendorDir = dirname(dirname(__FILE__));
 $baseDir = dirname($vendorDir);
 
 return array(
-    '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
     'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
+    '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
     '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
     'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php',
     '667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
diff --git a/data/web/inc/lib/vendor/composer/autoload_static.php b/data/web/inc/lib/vendor/composer/autoload_static.php
index 32f92e9d..4d3a5d44 100644
--- a/data/web/inc/lib/vendor/composer/autoload_static.php
+++ b/data/web/inc/lib/vendor/composer/autoload_static.php
@@ -7,8 +7,8 @@ namespace Composer\Autoload;
 class ComposerStaticInit873464e4bd965a3168f133248b1b218b
 {
     public static $files = array (
-        '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
         'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
+        '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
         '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
         'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php',
         '667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
diff --git a/data/web/inc/lib/vendor/composer/installed.json b/data/web/inc/lib/vendor/composer/installed.json
index e0ffaecd..1ff198c8 100644
--- a/data/web/inc/lib/vendor/composer/installed.json
+++ b/data/web/inc/lib/vendor/composer/installed.json
@@ -140,17 +140,17 @@
         },
         {
             "name": "directorytree/ldaprecord",
-            "version": "v2.5.0",
-            "version_normalized": "2.5.0.0",
+            "version": "v2.6.3",
+            "version_normalized": "2.6.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/DirectoryTree/LdapRecord.git",
-                "reference": "ff7a92615fdc3f8b7f3d347c2847ce7ce06db287"
+                "reference": "5c93ec6d1ef458290825a8b0a148946dce7c1e7a"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/ff7a92615fdc3f8b7f3d347c2847ce7ce06db287",
-                "reference": "ff7a92615fdc3f8b7f3d347c2847ce7ce06db287",
+                "url": "https://api.github.com/repos/DirectoryTree/LdapRecord/zipball/5c93ec6d1ef458290825a8b0a148946dce7c1e7a",
+                "reference": "5c93ec6d1ef458290825a8b0a148946dce7c1e7a",
                 "shasum": ""
             },
             "require": {
@@ -168,7 +168,7 @@
                 "phpunit/phpunit": "^8.0",
                 "spatie/ray": "^1.24"
             },
-            "time": "2021-06-06T18:51:41+00:00",
+            "time": "2021-08-05T21:52:43+00:00",
             "type": "library",
             "installation-source": "dist",
             "autoload": {
@@ -216,17 +216,17 @@
         },
         {
             "name": "illuminate/contracts",
-            "version": "v8.48.0",
-            "version_normalized": "8.48.0.0",
+            "version": "v8.53.1",
+            "version_normalized": "8.53.1.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/illuminate/contracts.git",
-                "reference": "199fcedc161ba4a0b83feaddc4629f395dbf1641"
+                "reference": "504a34286a1b4c5421c43087d6bd4e176138f6fb"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/illuminate/contracts/zipball/199fcedc161ba4a0b83feaddc4629f395dbf1641",
-                "reference": "199fcedc161ba4a0b83feaddc4629f395dbf1641",
+                "url": "https://api.github.com/repos/illuminate/contracts/zipball/504a34286a1b4c5421c43087d6bd4e176138f6fb",
+                "reference": "504a34286a1b4c5421c43087d6bd4e176138f6fb",
                 "shasum": ""
             },
             "require": {
@@ -234,7 +234,7 @@
                 "psr/container": "^1.0",
                 "psr/simple-cache": "^1.0"
             },
-            "time": "2021-06-01T14:53:38+00:00",
+            "time": "2021-08-03T14:03:47+00:00",
             "type": "library",
             "extra": {
                 "branch-alias": {
@@ -453,23 +453,24 @@
         },
         {
             "name": "nesbot/carbon",
-            "version": "2.49.0",
-            "version_normalized": "2.49.0.0",
+            "version": "2.51.1",
+            "version_normalized": "2.51.1.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/briannesbitt/Carbon.git",
-                "reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee"
+                "reference": "8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/93d9db91c0235c486875d22f1e08b50bdf3e6eee",
-                "reference": "93d9db91c0235c486875d22f1e08b50bdf3e6eee",
+                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922",
+                "reference": "8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922",
                 "shasum": ""
             },
             "require": {
                 "ext-json": "*",
                 "php": "^7.1.8 || ^8.0",
                 "symfony/polyfill-mbstring": "^1.0",
+                "symfony/polyfill-php80": "^1.16",
                 "symfony/translation": "^3.4 || ^4.0 || ^5.0"
             },
             "require-dev": {
@@ -482,15 +483,15 @@
                 "phpunit/phpunit": "^7.5.20 || ^8.5.14",
                 "squizlabs/php_codesniffer": "^3.4"
             },
-            "time": "2021-06-02T07:31:40+00:00",
+            "time": "2021-07-28T13:16:28+00:00",
             "bin": [
                 "bin/carbon"
             ],
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.x-dev",
-                    "dev-3.x": "3.x-dev"
+                    "dev-3.x": "3.x-dev",
+                    "dev-master": "2.x-dev"
                 },
                 "laravel": {
                     "providers": [
@@ -517,15 +518,15 @@
                 {
                     "name": "Brian Nesbitt",
                     "email": "[email protected]",
-                    "homepage": "http://nesbot.com"
+                    "homepage": "https://markido.com"
                 },
                 {
                     "name": "kylekatarnls",
-                    "homepage": "http://github.com/kylekatarnls"
+                    "homepage": "https://github.com/kylekatarnls"
                 }
             ],
             "description": "An API extension for DateTime that supports 281 different languages.",
-            "homepage": "http://carbon.nesbot.com",
+            "homepage": "https://carbon.nesbot.com",
             "keywords": [
                 "date",
                 "datetime",
@@ -602,34 +603,33 @@
         },
         {
             "name": "php-mime-mail-parser/php-mime-mail-parser",
-            "version": "5.0.5",
-            "version_normalized": "5.0.5.0",
+            "version": "7.0.0",
+            "version_normalized": "7.0.0.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/php-mime-mail-parser/php-mime-mail-parser.git",
-                "reference": "27983433aabeccee832573c3c56e6a4855e57745"
+                "reference": "9d09a017f3f103fec8456211a4a538b80e0eca0d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/php-mime-mail-parser/php-mime-mail-parser/zipball/27983433aabeccee832573c3c56e6a4855e57745",
-                "reference": "27983433aabeccee832573c3c56e6a4855e57745",
+                "url": "https://api.github.com/repos/php-mime-mail-parser/php-mime-mail-parser/zipball/9d09a017f3f103fec8456211a4a538b80e0eca0d",
+                "reference": "9d09a017f3f103fec8456211a4a538b80e0eca0d",
                 "shasum": ""
             },
             "require": {
                 "ext-mailparse": "*",
-                "php": "^7.1"
+                "php": "^7.2|^8.0"
             },
             "replace": {
                 "exorus/php-mime-mail-parser": "*",
                 "messaged/php-mime-mail-parser": "*"
             },
             "require-dev": {
-                "php-coveralls/php-coveralls": "^2.1",
-                "phpunit/php-token-stream": "^3.0",
-                "phpunit/phpunit": "^7.0",
-                "squizlabs/php_codesniffer": "^3.4"
+                "php-coveralls/php-coveralls": "^2.2",
+                "phpunit/phpunit": "^8.0",
+                "squizlabs/php_codesniffer": "^3.5"
             },
-            "time": "2019-09-23T11:57:58+00:00",
+            "time": "2021-02-25T17:21:57+00:00",
             "type": "library",
             "installation-source": "dist",
             "autoload": {
@@ -673,7 +673,7 @@
                     "role": "Developer"
                 }
             ],
-            "description": "A fully tested email parser for PHP 7.1+ (mailparse extension wrapper).",
+            "description": "A fully tested email parser for PHP 7.2+ (mailparse extension wrapper).",
             "homepage": "https://github.com/php-mime-mail-parser/php-mime-mail-parser",
             "keywords": [
                 "MimeMailParser",
@@ -683,6 +683,16 @@
                 "parser",
                 "php"
             ],
+            "support": {
+                "issues": "https://github.com/php-mime-mail-parser/php-mime-mail-parser/issues",
+                "source": "https://github.com/php-mime-mail-parser/php-mime-mail-parser/tree/7.0.0"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/eXorus",
+                    "type": "github"
+                }
+            ],
             "install-path": "../php-mime-mail-parser/php-mime-mail-parser"
         },
         {
@@ -1120,17 +1130,17 @@
         },
         {
             "name": "symfony/polyfill-mbstring",
-            "version": "v1.23.0",
-            "version_normalized": "1.23.0.0",
+            "version": "v1.23.1",
+            "version_normalized": "1.23.1.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-mbstring.git",
-                "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1"
+                "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
-                "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1",
+                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6",
+                "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6",
                 "shasum": ""
             },
             "require": {
@@ -1139,7 +1149,7 @@
             "suggest": {
                 "ext-mbstring": "For best performance"
             },
-            "time": "2021-05-27T09:27:20+00:00",
+            "time": "2021-05-27T12:26:48+00:00",
             "type": "library",
             "extra": {
                 "branch-alias": {
@@ -1183,7 +1193,7 @@
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0"
+                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1"
             },
             "funding": [
                 {
@@ -1203,23 +1213,23 @@
         },
         {
             "name": "symfony/polyfill-php80",
-            "version": "v1.23.0",
-            "version_normalized": "1.23.0.0",
+            "version": "v1.23.1",
+            "version_normalized": "1.23.1.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/polyfill-php80.git",
-                "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0"
+                "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0",
-                "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0",
+                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be",
+                "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be",
                 "shasum": ""
             },
             "require": {
                 "php": ">=7.1"
             },
-            "time": "2021-02-19T12:13:01+00:00",
+            "time": "2021-07-28T13:41:28+00:00",
             "type": "library",
             "extra": {
                 "branch-alias": {
@@ -1269,7 +1279,7 @@
                 "shim"
             ],
             "support": {
-                "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0"
+                "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1"
             },
             "funding": [
                 {
@@ -1289,24 +1299,24 @@
         },
         {
             "name": "symfony/translation",
-            "version": "v5.3.2",
-            "version_normalized": "5.3.2.0",
+            "version": "v5.3.4",
+            "version_normalized": "5.3.4.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/translation.git",
-                "reference": "7e2603bcc598e14804c4d2359d8dc4ee3c40391b"
+                "reference": "d89ad7292932c2699cbe4af98d72c5c6bbc504c1"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/translation/zipball/7e2603bcc598e14804c4d2359d8dc4ee3c40391b",
-                "reference": "7e2603bcc598e14804c4d2359d8dc4ee3c40391b",
+                "url": "https://api.github.com/repos/symfony/translation/zipball/d89ad7292932c2699cbe4af98d72c5c6bbc504c1",
+                "reference": "d89ad7292932c2699cbe4af98d72c5c6bbc504c1",
                 "shasum": ""
             },
             "require": {
                 "php": ">=7.2.5",
                 "symfony/deprecation-contracts": "^2.1",
                 "symfony/polyfill-mbstring": "~1.0",
-                "symfony/polyfill-php80": "^1.15",
+                "symfony/polyfill-php80": "^1.16",
                 "symfony/translation-contracts": "^2.3"
             },
             "conflict": {
@@ -1320,7 +1330,7 @@
                 "symfony/translation-implementation": "2.3"
             },
             "require-dev": {
-                "psr/log": "~1.0",
+                "psr/log": "^1|^2|^3",
                 "symfony/config": "^4.4|^5.0",
                 "symfony/console": "^4.4|^5.0",
                 "symfony/dependency-injection": "^5.0",
@@ -1336,7 +1346,7 @@
                 "symfony/config": "",
                 "symfony/yaml": ""
             },
-            "time": "2021-06-06T09:51:56+00:00",
+            "time": "2021-07-25T09:39:16+00:00",
             "type": "library",
             "installation-source": "dist",
             "autoload": {
@@ -1367,7 +1377,7 @@
             "description": "Provides tools to internationalize your application",
             "homepage": "https://symfony.com",
             "support": {
-                "source": "https://github.com/symfony/translation/tree/v5.3.2"
+                "source": "https://github.com/symfony/translation/tree/v5.3.4"
             },
             "funding": [
                 {
@@ -1468,23 +1478,23 @@
         },
         {
             "name": "symfony/var-dumper",
-            "version": "v5.3.2",
-            "version_normalized": "5.3.2.0",
+            "version": "v5.3.6",
+            "version_normalized": "5.3.6.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/var-dumper.git",
-                "reference": "905a22c68b292ffb6f20d7636c36b220d1fba5ae"
+                "reference": "3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/905a22c68b292ffb6f20d7636c36b220d1fba5ae",
-                "reference": "905a22c68b292ffb6f20d7636c36b220d1fba5ae",
+                "url": "https://api.github.com/repos/symfony/var-dumper/zipball/3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0",
+                "reference": "3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0",
                 "shasum": ""
             },
             "require": {
                 "php": ">=7.2.5",
                 "symfony/polyfill-mbstring": "~1.0",
-                "symfony/polyfill-php80": "^1.15"
+                "symfony/polyfill-php80": "^1.16"
             },
             "conflict": {
                 "phpunit/phpunit": "<5.4.3",
@@ -1501,7 +1511,7 @@
                 "ext-intl": "To show region name in time zone dump",
                 "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
             },
-            "time": "2021-06-06T09:51:56+00:00",
+            "time": "2021-07-27T01:56:02+00:00",
             "bin": [
                 "Resources/bin/var-dump-server"
             ],
@@ -1539,7 +1549,7 @@
                 "dump"
             ],
             "support": {
-                "source": "https://github.com/symfony/var-dumper/tree/v5.3.2"
+                "source": "https://github.com/symfony/var-dumper/tree/v5.3.6"
             },
             "funding": [
                 {
diff --git a/data/web/inc/lib/vendor/composer/installed.php b/data/web/inc/lib/vendor/composer/installed.php
index 84c3c9f2..2e6adce4 100644
--- a/data/web/inc/lib/vendor/composer/installed.php
+++ b/data/web/inc/lib/vendor/composer/installed.php
@@ -1,261 +1,257 @@
-<?php return array (
-  'root' => 
-  array (
-    'pretty_version' => '1.0.0+no-version-set',
-    'version' => '1.0.0.0',
-    'aliases' => 
-    array (
+<?php return array(
+    'root' => array(
+        'pretty_version' => '1.0.0+no-version-set',
+        'version' => '1.0.0.0',
+        'type' => 'library',
+        'install_path' => __DIR__ . '/../../',
+        'aliases' => array(),
+        'reference' => NULL,
+        'name' => '__root__',
+        'dev' => true,
     ),
-    'reference' => NULL,
-    'name' => '__root__',
-  ),
-  'versions' => 
-  array (
-    '__root__' => 
-    array (
-      'pretty_version' => '1.0.0+no-version-set',
-      'version' => '1.0.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => NULL,
+    'versions' => array(
+        '__root__' => array(
+            'pretty_version' => '1.0.0+no-version-set',
+            'version' => '1.0.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../../',
+            'aliases' => array(),
+            'reference' => NULL,
+            'dev_requirement' => false,
+        ),
+        'bshaffer/oauth2-server-php' => array(
+            'pretty_version' => 'v1.11.1',
+            'version' => '1.11.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../bshaffer/oauth2-server-php',
+            'aliases' => array(),
+            'reference' => '5a0c8000d4763b276919e2106f54eddda6bc50fa',
+            'dev_requirement' => false,
+        ),
+        'ddeboer/imap' => array(
+            'pretty_version' => '1.12.1',
+            'version' => '1.12.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../ddeboer/imap',
+            'aliases' => array(),
+            'reference' => 'dbed05ca67b93509345a820b2859de10c48948fb',
+            'dev_requirement' => false,
+        ),
+        'directorytree/ldaprecord' => array(
+            'pretty_version' => 'v2.6.3',
+            'version' => '2.6.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../directorytree/ldaprecord',
+            'aliases' => array(),
+            'reference' => '5c93ec6d1ef458290825a8b0a148946dce7c1e7a',
+            'dev_requirement' => false,
+        ),
+        'exorus/php-mime-mail-parser' => array(
+            'dev_requirement' => false,
+            'replaced' => array(
+                0 => '*',
+            ),
+        ),
+        'illuminate/contracts' => array(
+            'pretty_version' => 'v8.53.1',
+            'version' => '8.53.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../illuminate/contracts',
+            'aliases' => array(),
+            'reference' => '504a34286a1b4c5421c43087d6bd4e176138f6fb',
+            'dev_requirement' => false,
+        ),
+        'matthiasmullie/minify' => array(
+            'pretty_version' => '1.3.66',
+            'version' => '1.3.66.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../matthiasmullie/minify',
+            'aliases' => array(),
+            'reference' => '45fd3b0f1dfa2c965857c6d4a470bea52adc31a6',
+            'dev_requirement' => false,
+        ),
+        'matthiasmullie/path-converter' => array(
+            'pretty_version' => '1.1.3',
+            'version' => '1.1.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../matthiasmullie/path-converter',
+            'aliases' => array(),
+            'reference' => 'e7d13b2c7e2f2268e1424aaed02085518afa02d9',
+            'dev_requirement' => false,
+        ),
+        'messaged/php-mime-mail-parser' => array(
+            'dev_requirement' => false,
+            'replaced' => array(
+                0 => '*',
+            ),
+        ),
+        'mustangostang/spyc' => array(
+            'pretty_version' => '0.6.3',
+            'version' => '0.6.3.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../mustangostang/spyc',
+            'aliases' => array(),
+            'reference' => '4627c838b16550b666d15aeae1e5289dd5b77da0',
+            'dev_requirement' => false,
+        ),
+        'nesbot/carbon' => array(
+            'pretty_version' => '2.51.1',
+            'version' => '2.51.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../nesbot/carbon',
+            'aliases' => array(),
+            'reference' => '8619c299d1e0d4b344e1f98ca07a1ce2cfbf1922',
+            'dev_requirement' => false,
+        ),
+        'paragonie/random_compat' => array(
+            'pretty_version' => 'v9.99.100',
+            'version' => '9.99.100.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../paragonie/random_compat',
+            'aliases' => array(),
+            'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
+            'dev_requirement' => false,
+        ),
+        'php-mime-mail-parser/php-mime-mail-parser' => array(
+            'pretty_version' => '7.0.0',
+            'version' => '7.0.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../php-mime-mail-parser/php-mime-mail-parser',
+            'aliases' => array(),
+            'reference' => '9d09a017f3f103fec8456211a4a538b80e0eca0d',
+            'dev_requirement' => false,
+        ),
+        'phpmailer/phpmailer' => array(
+            'pretty_version' => 'v6.5.0',
+            'version' => '6.5.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../phpmailer/phpmailer',
+            'aliases' => array(),
+            'reference' => 'a5b5c43e50b7fba655f793ad27303cd74c57363c',
+            'dev_requirement' => false,
+        ),
+        'psr/container' => array(
+            'pretty_version' => '1.1.1',
+            'version' => '1.1.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/container',
+            'aliases' => array(),
+            'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf',
+            'dev_requirement' => false,
+        ),
+        'psr/log' => array(
+            'pretty_version' => '1.1.4',
+            'version' => '1.1.4.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/log',
+            'aliases' => array(),
+            'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
+            'dev_requirement' => false,
+        ),
+        'psr/simple-cache' => array(
+            'pretty_version' => '1.0.1',
+            'version' => '1.0.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../psr/simple-cache',
+            'aliases' => array(),
+            'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
+            'dev_requirement' => false,
+        ),
+        'robthree/twofactorauth' => array(
+            'pretty_version' => '1.8.0',
+            'version' => '1.8.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../robthree/twofactorauth',
+            'aliases' => array(),
+            'reference' => '30a38627ae1e7c9399dae67e265063cd6ec5276c',
+            'dev_requirement' => false,
+        ),
+        'soundasleep/html2text' => array(
+            'pretty_version' => '0.5.0',
+            'version' => '0.5.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../soundasleep/html2text',
+            'aliases' => array(),
+            'reference' => 'cdb89f6ffa2c4cc78f8ed9ea6ee0594a9133ccad',
+            'dev_requirement' => false,
+        ),
+        'symfony/deprecation-contracts' => array(
+            'pretty_version' => 'v2.4.0',
+            'version' => '2.4.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
+            'aliases' => array(),
+            'reference' => '5f38c8804a9e97d23e0c8d63341088cd8a22d627',
+            'dev_requirement' => false,
+        ),
+        'symfony/polyfill-mbstring' => array(
+            'pretty_version' => 'v1.23.1',
+            'version' => '1.23.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
+            'aliases' => array(),
+            'reference' => '9174a3d80210dca8daa7f31fec659150bbeabfc6',
+            'dev_requirement' => false,
+        ),
+        'symfony/polyfill-php80' => array(
+            'pretty_version' => 'v1.23.1',
+            'version' => '1.23.1.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/polyfill-php80',
+            'aliases' => array(),
+            'reference' => '1100343ed1a92e3a38f9ae122fc0eb21602547be',
+            'dev_requirement' => false,
+        ),
+        'symfony/translation' => array(
+            'pretty_version' => 'v5.3.4',
+            'version' => '5.3.4.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/translation',
+            'aliases' => array(),
+            'reference' => 'd89ad7292932c2699cbe4af98d72c5c6bbc504c1',
+            'dev_requirement' => false,
+        ),
+        'symfony/translation-contracts' => array(
+            'pretty_version' => 'v2.4.0',
+            'version' => '2.4.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/translation-contracts',
+            'aliases' => array(),
+            'reference' => '95c812666f3e91db75385749fe219c5e494c7f95',
+            'dev_requirement' => false,
+        ),
+        'symfony/translation-implementation' => array(
+            'dev_requirement' => false,
+            'provided' => array(
+                0 => '2.3',
+            ),
+        ),
+        'symfony/var-dumper' => array(
+            'pretty_version' => 'v5.3.6',
+            'version' => '5.3.6.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../symfony/var-dumper',
+            'aliases' => array(),
+            'reference' => '3dd8ddd1e260e58ecc61bb78da3b6584b3bfcba0',
+            'dev_requirement' => false,
+        ),
+        'tightenco/collect' => array(
+            'pretty_version' => 'v8.34.0',
+            'version' => '8.34.0.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../tightenco/collect',
+            'aliases' => array(),
+            'reference' => 'b069783ab0c547bb894ebcf8e7f6024bb401f9d2',
+            'dev_requirement' => false,
+        ),
+        'yubico/u2flib-server' => array(
+            'pretty_version' => '1.0.2',
+            'version' => '1.0.2.0',
+            'type' => 'library',
+            'install_path' => __DIR__ . '/../yubico/u2flib-server',
+            'aliases' => array(),
+            'reference' => '55d813acf68212ad2cadecde07551600d6971939',
+            'dev_requirement' => false,
+        ),
     ),
-    'bshaffer/oauth2-server-php' => 
-    array (
-      'pretty_version' => 'v1.11.1',
-      'version' => '1.11.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '5a0c8000d4763b276919e2106f54eddda6bc50fa',
-    ),
-    'ddeboer/imap' => 
-    array (
-      'pretty_version' => '1.12.1',
-      'version' => '1.12.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'dbed05ca67b93509345a820b2859de10c48948fb',
-    ),
-    'directorytree/ldaprecord' => 
-    array (
-      'pretty_version' => 'v2.5.0',
-      'version' => '2.5.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'ff7a92615fdc3f8b7f3d347c2847ce7ce06db287',
-    ),
-    'exorus/php-mime-mail-parser' => 
-    array (
-      'replaced' => 
-      array (
-        0 => '*',
-      ),
-    ),
-    'illuminate/contracts' => 
-    array (
-      'pretty_version' => 'v8.48.0',
-      'version' => '8.48.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '199fcedc161ba4a0b83feaddc4629f395dbf1641',
-    ),
-    'matthiasmullie/minify' => 
-    array (
-      'pretty_version' => '1.3.66',
-      'version' => '1.3.66.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '45fd3b0f1dfa2c965857c6d4a470bea52adc31a6',
-    ),
-    'matthiasmullie/path-converter' => 
-    array (
-      'pretty_version' => '1.1.3',
-      'version' => '1.1.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'e7d13b2c7e2f2268e1424aaed02085518afa02d9',
-    ),
-    'messaged/php-mime-mail-parser' => 
-    array (
-      'replaced' => 
-      array (
-        0 => '*',
-      ),
-    ),
-    'mustangostang/spyc' => 
-    array (
-      'pretty_version' => '0.6.3',
-      'version' => '0.6.3.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '4627c838b16550b666d15aeae1e5289dd5b77da0',
-    ),
-    'nesbot/carbon' => 
-    array (
-      'pretty_version' => '2.49.0',
-      'version' => '2.49.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '93d9db91c0235c486875d22f1e08b50bdf3e6eee',
-    ),
-    'paragonie/random_compat' => 
-    array (
-      'pretty_version' => 'v9.99.100',
-      'version' => '9.99.100.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
-    ),
-    'php-mime-mail-parser/php-mime-mail-parser' => 
-    array (
-      'pretty_version' => '5.0.5',
-      'version' => '5.0.5.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '27983433aabeccee832573c3c56e6a4855e57745',
-    ),
-    'phpmailer/phpmailer' => 
-    array (
-      'pretty_version' => 'v6.5.0',
-      'version' => '6.5.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'a5b5c43e50b7fba655f793ad27303cd74c57363c',
-    ),
-    'psr/container' => 
-    array (
-      'pretty_version' => '1.1.1',
-      'version' => '1.1.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf',
-    ),
-    'psr/log' => 
-    array (
-      'pretty_version' => '1.1.4',
-      'version' => '1.1.4.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
-    ),
-    'psr/simple-cache' => 
-    array (
-      'pretty_version' => '1.0.1',
-      'version' => '1.0.1.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
-    ),
-    'robthree/twofactorauth' => 
-    array (
-      'pretty_version' => '1.8.0',
-      'version' => '1.8.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '30a38627ae1e7c9399dae67e265063cd6ec5276c',
-    ),
-    'soundasleep/html2text' => 
-    array (
-      'pretty_version' => '0.5.0',
-      'version' => '0.5.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'cdb89f6ffa2c4cc78f8ed9ea6ee0594a9133ccad',
-    ),
-    'symfony/deprecation-contracts' => 
-    array (
-      'pretty_version' => 'v2.4.0',
-      'version' => '2.4.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '5f38c8804a9e97d23e0c8d63341088cd8a22d627',
-    ),
-    'symfony/polyfill-mbstring' => 
-    array (
-      'pretty_version' => 'v1.23.0',
-      'version' => '1.23.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '2df51500adbaebdc4c38dea4c89a2e131c45c8a1',
-    ),
-    'symfony/polyfill-php80' => 
-    array (
-      'pretty_version' => 'v1.23.0',
-      'version' => '1.23.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'eca0bf41ed421bed1b57c4958bab16aa86b757d0',
-    ),
-    'symfony/translation' => 
-    array (
-      'pretty_version' => 'v5.3.2',
-      'version' => '5.3.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '7e2603bcc598e14804c4d2359d8dc4ee3c40391b',
-    ),
-    'symfony/translation-contracts' => 
-    array (
-      'pretty_version' => 'v2.4.0',
-      'version' => '2.4.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '95c812666f3e91db75385749fe219c5e494c7f95',
-    ),
-    'symfony/translation-implementation' => 
-    array (
-      'provided' => 
-      array (
-        0 => '2.3',
-      ),
-    ),
-    'symfony/var-dumper' => 
-    array (
-      'pretty_version' => 'v5.3.2',
-      'version' => '5.3.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '905a22c68b292ffb6f20d7636c36b220d1fba5ae',
-    ),
-    'tightenco/collect' => 
-    array (
-      'pretty_version' => 'v8.34.0',
-      'version' => '8.34.0.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => 'b069783ab0c547bb894ebcf8e7f6024bb401f9d2',
-    ),
-    'yubico/u2flib-server' => 
-    array (
-      'pretty_version' => '1.0.2',
-      'version' => '1.0.2.0',
-      'aliases' => 
-      array (
-      ),
-      'reference' => '55d813acf68212ad2cadecde07551600d6971939',
-    ),
-  ),
 );
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/bug_report.md b/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/bug_report.md
index dfcd8551..a56a2afb 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/bug_report.md
@@ -7,8 +7,9 @@ assignees: ''
 
 ---
 
-**Environment (please complete the following information):**
+<!-- Please update the below information with your environment. -->
+**Environment:**
  - LDAP Server Type: [e.g. ActiveDirectory / OpenLDAP / FreeIPA]
- - PHP Version: [e.g. 7.2 / 7.3 / 7.4]
+ - PHP Version: [e.g. 7.3 / 7.4 / 8.0]
 
 **Describe the bug:**
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/support---help-request.md b/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/support---help-request.md
index b8df7740..230916cf 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/support---help-request.md
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/ISSUE_TEMPLATE/support---help-request.md
@@ -10,3 +10,8 @@ assignees: ''
 <!-- ISSUE WILL BE CLOSED WITHOUT SPONSORSHIP: -->
 <!-- https://github.com/sponsors/stevebauman -->
 <!-- Thank you for your understanding. -->
+
+<!-- Please update the below information with your environment. -->
+**Environment:**
+ - LDAP Server Type: [e.g. ActiveDirectory / OpenLDAP / FreeIPA]
+ - PHP Version: [e.g. 7.3 / 7.4 / 8.0]
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-tests.yml b/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-tests.yml
index 613f85d5..ba002183 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-tests.yml
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-tests.yml
@@ -8,13 +8,14 @@ on:
 
 jobs:
   run-tests:
-    runs-on: ubuntu-latest
+    runs-on: ${{ matrix.os }}
     strategy:
       fail-fast: false
       matrix:
+        os: [ubuntu-latest, windows-latest]
         php: [8.0, 7.4, 7.3]
 
-    name: P${{ matrix.php }}
+    name: ${{ matrix.os }} - P${{ matrix.php }}
 
     steps:
       - name: Checkout code
@@ -34,7 +35,7 @@ jobs:
           coverage: none
 
       - name: Install dependencies
-        run: composer update --prefer-dist --no-interaction --no-suggest
+        run: composer update --prefer-dist --no-interaction
 
       - name: Execute tests
         run: vendor/bin/phpunit
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/ArrayValidator.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/ArrayValidator.php
index 5584fff9..4aa43ed4 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/ArrayValidator.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/ArrayValidator.php
@@ -2,19 +2,20 @@
 
 namespace LdapRecord\Configuration\Validators;
 
-use LdapRecord\Configuration\ConfigurationException;
-
 class ArrayValidator extends Validator
 {
+    /**
+     * The validation exception message.
+     *
+     * @var string
+     */
+    protected $message = 'Option [:option] must be an array.';
+
     /**
      * @inheritdoc
      */
-    public function validate()
+    public function passes()
     {
-        if (! is_array($this->value)) {
-            throw new ConfigurationException("Option {$this->key} must be an array.");
-        }
-
-        return true;
+        return is_array($this->value);
     }
 }
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/BooleanValidator.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/BooleanValidator.php
index a5e3cf33..1d25a4b2 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/BooleanValidator.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/BooleanValidator.php
@@ -2,19 +2,20 @@
 
 namespace LdapRecord\Configuration\Validators;
 
-use LdapRecord\Configuration\ConfigurationException;
-
 class BooleanValidator extends Validator
 {
+    /**
+     * The validation exception message.
+     *
+     * @var string
+     */
+    protected $message = 'Option [:option] must be a boolean.';
+
     /**
      * @inheritdoc
      */
-    public function validate()
+    public function passes()
     {
-        if (! is_bool($this->value)) {
-            throw new ConfigurationException("Option {$this->key} must be a boolean.");
-        }
-
-        return true;
+        return is_bool($this->value);
     }
 }
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/IntegerValidator.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/IntegerValidator.php
index 796b3358..5c4f0f95 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/IntegerValidator.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/IntegerValidator.php
@@ -2,19 +2,20 @@
 
 namespace LdapRecord\Configuration\Validators;
 
-use LdapRecord\Configuration\ConfigurationException;
-
 class IntegerValidator extends Validator
 {
+    /**
+     * The validation exception message.
+     *
+     * @var string
+     */
+    protected $message = 'Option [:option] must be an integer.';
+
     /**
      * @inheritdoc
      */
-    public function validate()
+    public function passes()
     {
-        if (! is_numeric($this->value)) {
-            throw new ConfigurationException("Option {$this->key} must be an integer.");
-        }
-
-        return true;
+        return is_numeric($this->value);
     }
 }
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/StringOrNullValidator.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/StringOrNullValidator.php
index b0ff565c..bc233724 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/StringOrNullValidator.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/StringOrNullValidator.php
@@ -2,19 +2,20 @@
 
 namespace LdapRecord\Configuration\Validators;
 
-use LdapRecord\Configuration\ConfigurationException;
-
 class StringOrNullValidator extends Validator
 {
+    /**
+     * The validation exception message.
+     *
+     * @var string
+     */
+    protected $message = 'Option [:option] must be a string or null.';
+
     /**
      * @inheritdoc
      */
-    public function validate()
+    public function passes()
     {
-        if (is_string($this->value) || is_null($this->value)) {
-            return true;
-        }
-
-        throw new ConfigurationException("Option {$this->key} must be a string or null.");
+        return is_string($this->value) || is_null($this->value);
     }
 }
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/Validator.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/Validator.php
index 4bf7ab73..908a6395 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/Validator.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Configuration/Validators/Validator.php
@@ -2,6 +2,8 @@
 
 namespace LdapRecord\Configuration\Validators;
 
+use LdapRecord\Configuration\ConfigurationException;
+
 abstract class Validator
 {
     /**
@@ -18,6 +20,13 @@ abstract class Validator
      */
     protected $value;
 
+    /**
+     * The validation exception message.
+     *
+     * @var string
+     */
+    protected $message;
+
     /**
      * Constructor.
      *
@@ -31,11 +40,39 @@ abstract class Validator
     }
 
     /**
-     * Validates the configuration value.
+     * Determine if the validation rule passes.
+     *
+     * @return bool
+     */
+    abstract public function passes();
+
+    /**
+     * Validate the configuration value.
      *
-     * @throws \LdapRecord\Configuration\ConfigurationException When the value given fails validation.
+     * @throws ConfigurationException
      *
      * @return bool
      */
-    abstract public function validate();
+    public function validate()
+    {
+        if (! $this->passes()) {
+            $this->fail();
+        }
+
+        return true;
+    }
+
+    /**
+     * Throw a configuration exception.
+     *
+     * @throws ConfigurationException
+     *
+     * @return void
+     */
+    protected function fail()
+    {
+        throw new ConfigurationException(
+            str_replace(':option', $this->key, $this->message)
+        );
+    }
 }
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Connection.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Connection.php
index beca5138..8ba0ef1d 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Connection.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Connection.php
@@ -74,7 +74,7 @@ class Connection
     /**
      * The authentication guard resolver.
      *
-     * @var \Closure
+     * @var Closure
      */
     protected $authGuardResolver;
 
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/ConnectionManager.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/ConnectionManager.php
new file mode 100644
index 00000000..0eacbc3f
--- /dev/null
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/ConnectionManager.php
@@ -0,0 +1,320 @@
+<?php
+
+namespace LdapRecord;
+
+use BadMethodCallException;
+use LdapRecord\Events\Dispatcher;
+use LdapRecord\Events\DispatcherInterface;
+use LdapRecord\Events\Logger;
+use Psr\Log\LoggerInterface;
+
+class ConnectionManager
+{
+    /**
+     * The logger instance.
+     *
+     * @var LoggerInterface|null
+     */
+    protected $logger;
+
+    /**
+     * The event dispatcher instance.
+     *
+     * @var DispatcherInterface|null
+     */
+    protected $dispatcher;
+
+    /**
+     * The added LDAP connections.
+     *
+     * @var Connection[]
+     */
+    protected $connections = [];
+
+    /**
+     * The name of the default connection.
+     *
+     * @var string
+     */
+    protected $default = 'default';
+
+    /**
+     * The events to register listeners for during initialization.
+     *
+     * @var array
+     */
+    protected $listen = [
+        'LdapRecord\Auth\Events\*',
+        'LdapRecord\Query\Events\*',
+        'LdapRecord\Models\Events\*',
+    ];
+
+    /**
+     * The method calls to proxy for compatibility.
+     *
+     * To be removed in the next major version.
+     *
+     * @var array
+     */
+    protected $proxy = [
+        'reset' => 'flush',
+        'addConnection' => 'add',
+        'getConnection' => 'get',
+        'allConnections' => 'all',
+        'removeConnection' => 'remove',
+        'getDefaultConnection' => 'getDefault',
+        'setDefaultConnection' => 'setDefault',
+        'getEventDispatcher' => 'dispatcher',
+        'setEventDispatcher' => 'setDispatcher',
+    ];
+
+    /**
+     * Constructor.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        $this->dispatcher = new Dispatcher();
+    }
+
+    /**
+     * Forward missing method calls onto the instance.
+     *
+     * @param string $method
+     * @param mixed  $args
+     *
+     * @return mixed
+     */
+    public function __call($method, $args)
+    {
+        $method = $this->proxy[$method] ?? $method;
+
+        if (! method_exists($this, $method)) {
+            throw new BadMethodCallException(sprintf(
+                'Call to undefined method %s::%s()',
+                static::class,
+                $method
+            ));
+        }
+
+        return $this->{$method}(...$args);
+    }
+
+    /**
+     * Add a new connection.
+     *
+     * @param Connection  $connection
+     * @param string|null $name
+     *
+     * @return $this
+     */
+    public function add(Connection $connection, $name = null)
+    {
+        $this->connections[$name ?? $this->default] = $connection;
+
+        if ($this->dispatcher) {
+            $connection->setDispatcher($this->dispatcher);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Remove a connection.
+     *
+     * @param $name
+     *
+     * @return $this
+     */
+    public function remove($name)
+    {
+        unset($this->connections[$name]);
+
+        return $this;
+    }
+
+    /**
+     * Get all of the connections.
+     *
+     * @return Connection[]
+     */
+    public function all()
+    {
+        return $this->connections;
+    }
+
+    /**
+     * Get a connection by name or return the default.
+     *
+     * @param string|null $name
+     *
+     * @throws ContainerException If the given connection does not exist.
+     *
+     * @return Connection
+     */
+    public function get($name = null)
+    {
+        if ($this->exists($name = $name ?? $this->default)) {
+            return $this->connections[$name];
+        }
+
+        throw new ContainerException("The LDAP connection [$name] does not exist.");
+    }
+
+    /**
+     * Return the default connection.
+     *
+     * @return Connection
+     */
+    public function getDefault()
+    {
+        return $this->get($this->default);
+    }
+
+    /**
+     * Get the default connection name.
+     *
+     * @return string
+     */
+    public function getDefaultConnectionName()
+    {
+        return $this->default;
+    }
+
+    /**
+     * Checks if the connection exists.
+     *
+     * @param string $name
+     *
+     * @return bool
+     */
+    public function exists($name)
+    {
+        return array_key_exists($name, $this->connections);
+    }
+
+    /**
+     * Set the default connection name.
+     *
+     * @param string $name
+     *
+     * @return $this
+     */
+    public function setDefault($name = null)
+    {
+        $this->default = $name;
+
+        return $this;
+    }
+
+    /**
+     * Flush the manager of all instances and connections.
+     *
+     * @return $this
+     */
+    public function flush()
+    {
+        $this->logger = null;
+
+        $this->connections = [];
+
+        $this->dispatcher = new Dispatcher();
+
+        return $this;
+    }
+
+    /**
+     * Get the logger instance.
+     *
+     * @return LoggerInterface|null
+     */
+    public function getLogger()
+    {
+        return $this->logger;
+    }
+
+    /**
+     * Set the event logger to use.
+     *
+     * @param LoggerInterface $logger
+     *
+     * @return void
+     */
+    public function setLogger(LoggerInterface $logger)
+    {
+        $this->logger = $logger;
+
+        $this->initEventLogger();
+    }
+
+    /**
+     * Initialize the event logger.
+     *
+     * @return void
+     */
+    public function initEventLogger()
+    {
+        $logger = $this->newEventLogger();
+
+        foreach ($this->listen as $event) {
+            $this->dispatcher->listen($event, function ($eventName, $events) use ($logger) {
+                foreach ($events as $event) {
+                    $logger->log($event);
+                }
+            });
+        }
+    }
+
+    /**
+     * Make a new event logger instance.
+     *
+     * @return Logger
+     */
+    protected function newEventLogger()
+    {
+        return new Logger($this->logger);
+    }
+
+    /**
+     * Unset the logger instance.
+     *
+     * @return void
+     */
+    public function unsetLogger()
+    {
+        $this->logger = null;
+    }
+
+    /**
+     * Get the event dispatcher.
+     *
+     * @return DispatcherInterface|null
+     */
+    public function dispatcher()
+    {
+        return $this->dispatcher;
+    }
+
+    /**
+     * Set the event dispatcher.
+     *
+     * @param DispatcherInterface $dispatcher
+     *
+     * @return void
+     */
+    public function setDispatcher(DispatcherInterface $dispatcher)
+    {
+        $this->dispatcher = $dispatcher;
+    }
+
+    /**
+     * Unset the event dispatcher.
+     *
+     * @return void
+     */
+    public function unsetEventDispatcher()
+    {
+        $this->dispatcher = null;
+    }
+}
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Container.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Container.php
index d41f43f0..f458951e 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Container.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Container.php
@@ -2,11 +2,21 @@
 
 namespace LdapRecord;
 
-use LdapRecord\Events\Dispatcher;
-use LdapRecord\Events\DispatcherInterface;
-use LdapRecord\Events\Logger;
-use Psr\Log\LoggerInterface;
-
+/**
+ * @method static $this reset()
+ * @method static Connection[] all()
+ * @method static Connection[] allConnections()
+ * @method static Connection getDefaultConnection()
+ * @method static Connection get(string|null $name = null)
+ * @method static Connection getConnection(string|null $name = null)
+ * @method static bool exists(string $name)
+ * @method static $this remove(string|null $name = null)
+ * @method static $this removeConnection(string|null $name = null)
+ * @method static $this setDefault(string|null $name = null)
+ * @method static $this setDefaultConnection(string|null $name = null)
+ * @method static $this add(Connection $connection, string|null $name = null)
+ * @method static $this addConnection(Connection $connection, string|null $name = null)
+ */
 class Container
 {
     /**
@@ -17,43 +27,36 @@ class Container
     protected static $instance;
 
     /**
-     * The logger instance.
-     *
-     * @var LoggerInterface|null
-     */
-    protected $logger;
-
-    /**
-     * The event dispatcher instance.
+     * The connection manager instance.
      *
-     * @var DispatcherInterface|null
+     * @var ConnectionManager
      */
-    protected $dispatcher;
+    protected $manager;
 
     /**
-     * The added connections in the container instance.
+     * The methods to passthru, for compatibility.
      *
-     * @var Connection[]
+     * @var array
      */
-    protected $connections = [];
+    protected $passthru = [
+        'reset', 'flush',
+        'add', 'addConnection',
+        'remove', 'removeConnection',
+        'setDefault', 'setDefaultConnection',
+    ];
 
     /**
-     * The name of the default connection.
+     * Forward missing static calls onto the current instance.
      *
-     * @var string
-     */
-    protected $default = 'default';
-
-    /**
-     * The events to register listeners for during initialization.
+     * @param string $method
+     * @param mixed  $args
      *
-     * @var array
+     * @return mixed
      */
-    protected $listen = [
-        'LdapRecord\Auth\Events\*',
-        'LdapRecord\Query\Events\*',
-        'LdapRecord\Models\Events\*',
-    ];
+    public static function __callStatic($method, $args)
+    {
+        return static::getInstance()->{$method}(...$args);
+    }
 
     /**
      * Get or set the current instance of the container.
@@ -88,320 +91,37 @@ class Container
     }
 
     /**
-     * Add a connection to the container.
-     *
-     * @param Connection  $connection
-     * @param string|null $name
-     *
-     * @return static
-     */
-    public static function addConnection(Connection $connection, $name = null)
-    {
-        return static::getInstance()->add($connection, $name);
-    }
-
-    /**
-     * Remove a connection from the container.
-     *
-     * @param string $name
-     *
-     * @return void
-     */
-    public static function removeConnection($name)
-    {
-        static::getInstance()->remove($name);
-    }
-
-    /**
-     * Get a connection by name or return the default.
-     *
-     * @param string|null $name
-     *
-     * @throws ContainerException If the given connection does not exist.
-     *
-     * @return Connection
-     */
-    public static function getConnection($name = null)
-    {
-        return static::getInstance()->get($name);
-    }
-
-    /**
-     * Set the default connection name.
-     *
-     * @param string|null $name
-     *
-     * @return static
-     */
-    public static function setDefaultConnection($name = null)
-    {
-        return static::getInstance()->setDefault($name);
-    }
-
-    /**
-     * Get the default connection.
-     *
-     * @return Connection
-     */
-    public static function getDefaultConnection()
-    {
-        return static::getInstance()->getDefault();
-    }
-
-    /**
-     * Flush all of the added connections and reset the container.
-     *
-     * @return $this
-     */
-    public static function reset()
-    {
-        return static::getInstance()->flush();
-    }
-
-    /**
-     * Get the container dispatcher instance.
-     *
-     * @return DispatcherInterface
-     */
-    public static function getEventDispatcher()
-    {
-        $instance = static::getInstance();
-
-        if (! ($dispatcher = $instance->dispatcher())) {
-            $instance->setDispatcher($dispatcher = new Dispatcher());
-        }
-
-        return $dispatcher;
-    }
-
-    /**
-     * Set the container dispatcher instance.
-     *
-     * @param DispatcherInterface $dispatcher
+     * Constructor.
      *
      * @return void
      */
-    public static function setEventDispatcher(DispatcherInterface $dispatcher)
-    {
-        static::getInstance()->setDispatcher($dispatcher);
-    }
-
-    /**
-     * Get the container dispatcher instance.
-     *
-     * @return DispatcherInterface|null
-     */
-    public function dispatcher()
+    public function __construct()
     {
-        return $this->dispatcher;
+        $this->manager = new ConnectionManager();
     }
 
     /**
-     * Set the container dispatcher instance.
-     *
-     * @param DispatcherInterface $dispatcher
+     * Forward missing method calls onto the connection manager.
      *
-     * @return void
-     */
-    public function setDispatcher(DispatcherInterface $dispatcher)
-    {
-        $this->dispatcher = $dispatcher;
-    }
-
-    /**
-     * Unset the event dispatcher instance.
+     * @param string $method
+     * @param mixed  $args
      *
-     * @return void
+     * @return mixed
      */
-    public function unsetEventDispatcher()
+    public function __call($method, $args)
     {
-        $this->dispatcher = null;
-    }
+        $value = $this->manager->{$method}(...$args);
 
-    /**
-     * Get the logger instance.
-     *
-     * @return LoggerInterface|null
-     */
-    public function getLogger()
-    {
-        return $this->logger;
+        return in_array($method, $this->passthru) ? $this : $value;
     }
 
     /**
-     * Set the event logger to use.
-     *
-     * @param LoggerInterface $logger
+     * Get the connection manager.
      *
-     * @return void
+     * @return ConnectionManager
      */
-    public function setLogger(LoggerInterface $logger)
+    public function manager()
     {
-        $this->logger = $logger;
-
-        $this->initEventLogger();
-    }
-
-    /**
-     * Initializes the event logger.
-     *
-     * @return void
-     */
-    public function initEventLogger()
-    {
-        $dispatcher = $this->getEventDispatcher();
-
-        $logger = $this->newEventLogger();
-
-        foreach ($this->listen as $event) {
-            $dispatcher->listen($event, function ($eventName, $events) use ($logger) {
-                foreach ($events as $event) {
-                    $logger->log($event);
-                }
-            });
-        }
-    }
-
-    /**
-     * Returns a new event logger instance.
-     *
-     * @return Logger
-     */
-    protected function newEventLogger()
-    {
-        return new Logger($this->logger);
-    }
-
-    /**
-     * Unset the logger instance.
-     *
-     * @return void
-     */
-    public function unsetLogger()
-    {
-        $this->logger = null;
-    }
-
-    /**
-     * Add a new connection into the container.
-     *
-     * @param Connection  $connection
-     * @param string|null $name
-     *
-     * @return $this
-     */
-    public function add(Connection $connection, $name = null)
-    {
-        $this->connections[$name ?? $this->default] = $connection;
-
-        if ($this->dispatcher) {
-            $connection->setDispatcher($this->dispatcher);
-        }
-
-        return $this;
-    }
-
-    /**
-     * Remove a connection from the container.
-     *
-     * @param $name
-     *
-     * @return $this
-     */
-    public function remove($name)
-    {
-        if ($this->exists($name)) {
-            unset($this->connections[$name]);
-        }
-
-        return $this;
-    }
-
-    /**
-     * Return all of the connections from the container.
-     *
-     * @return Connection[]
-     */
-    public function all()
-    {
-        return $this->connections;
-    }
-
-    /**
-     * Get a connection by name or return the default.
-     *
-     * @param string|null $name
-     *
-     * @throws ContainerException If the given connection does not exist.
-     *
-     * @return Connection
-     */
-    public function get($name = null)
-    {
-        if ($this->exists($name = $name ?? $this->default)) {
-            return $this->connections[$name];
-        }
-
-        throw new ContainerException("The LDAP connection [$name] does not exist.");
-    }
-
-    /**
-     * Return the default connection.
-     *
-     * @return Connection
-     */
-    public function getDefault()
-    {
-        return $this->get($this->default);
-    }
-
-    /**
-     * Get the default connection name.
-     *
-     * @return string
-     */
-    public function getDefaultConnectionName()
-    {
-        return $this->default;
-    }
-
-    /**
-     * Checks if the connection exists.
-     *
-     * @param $name
-     *
-     * @return bool
-     */
-    public function exists($name)
-    {
-        return array_key_exists($name, $this->connections);
-    }
-
-    /**
-     * Set the default connection name.
-     *
-     * @param string $name
-     *
-     * @return $this
-     */
-    public function setDefault($name = null)
-    {
-        $this->default = $name;
-
-        return $this;
-    }
-
-    /**
-     * Flush the container of all instances and connections.
-     *
-     * @return $this
-     */
-    public function flush()
-    {
-        $this->connections = [];
-        $this->dispatcher = null;
-        $this->logger = null;
-
-        return $this;
+        return $this->manager;
     }
 }
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Logger.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Logger.php
index 708a1458..f3840c28 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Logger.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Events/Logger.php
@@ -118,7 +118,7 @@ class Logger
 
             $message = "LDAP ({$connection->getHost()})"
                 ." - Operation: {$this->getOperationName($event)}"
-                ." - Base DN: {$query->getDn()}"
+                ." - Base DN: {$query->getBaseDn()}"
                 ." - Filter: {$query->getQuery()}"
                 ." - Selected: ({$selected})"
                 ." - Time Elapsed: {$event->getTime()}";
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/LdapBase.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/HandlesConnection.php
similarity index 95%
rename from data/web/inc/lib/vendor/directorytree/ldaprecord/src/LdapBase.php
rename to data/web/inc/lib/vendor/directorytree/ldaprecord/src/HandlesConnection.php
index 2a3c2265..41334b68 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/LdapBase.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/HandlesConnection.php
@@ -6,10 +6,8 @@ use Closure;
 use ErrorException;
 use Exception;
 
-abstract class LdapBase implements LdapInterface
+trait HandlesConnection
 {
-    use DetectsErrors;
-
     /**
      * The LDAP host that is currently connected.
      *
@@ -136,7 +134,7 @@ abstract class LdapBase implements LdapInterface
      */
     public function getProtocol()
     {
-        return $this->isUsingSSL() ? $this::PROTOCOL_SSL : $this::PROTOCOL;
+        return $this->isUsingSSL() ? LdapInterface::PROTOCOL_SSL : LdapInterface::PROTOCOL;
     }
 
     /**
@@ -214,7 +212,7 @@ abstract class LdapBase implements LdapInterface
     /**
      * Determine if the current PHP version supports server controls.
      *
-     * @deprecated
+     * @deprecated since v2.5.0
      *
      * @return bool
      */
@@ -236,8 +234,8 @@ abstract class LdapBase implements LdapInterface
         // If an attempt to connect via SSL protocol is being performed,
         // and we are still using the default port, we will swap it
         // for the default SSL port, for developer convenience.
-        if ($this->isUsingSSL() && $port == static::PORT) {
-            $port = static::PORT_SSL;
+        if ($this->isUsingSSL() && $port == LdapInterface::PORT) {
+            $port = LdapInterface::PORT_SSL;
         }
 
         // The blank space here is intentional. PHP's LDAP extension
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Ldap.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Ldap.php
index 8098d9c4..6503cead 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Ldap.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Ldap.php
@@ -2,8 +2,10 @@
 
 namespace LdapRecord;
 
-class Ldap extends LdapBase
+class Ldap implements LdapInterface
 {
+    use HandlesConnection, DetectsErrors;
+
     /**
      * @inheritdoc
      */
@@ -17,9 +19,9 @@ class Ldap extends LdapBase
     /**
      * Retrieves the first entry from a search result.
      *
-     * @link http://php.net/manual/en/function.ldap-first-entry.php
+     * @see http://php.net/manual/en/function.ldap-first-entry.php
      *
-     * @param resource $searchResult
+     * @param resource $searchResults
      *
      * @return resource
      */
@@ -33,7 +35,7 @@ class Ldap extends LdapBase
     /**
      * Retrieves the next entry from a search result.
      *
-     * @link http://php.net/manual/en/function.ldap-next-entry.php
+     * @see http://php.net/manual/en/function.ldap-next-entry.php
      *
      * @param resource $entry
      *
@@ -49,7 +51,7 @@ class Ldap extends LdapBase
     /**
      * Retrieves the ldap entry's attributes.
      *
-     * @link http://php.net/manual/en/function.ldap-get-attributes.php
+     * @see http://php.net/manual/en/function.ldap-get-attributes.php
      *
      * @param resource $entry
      *
@@ -65,9 +67,9 @@ class Ldap extends LdapBase
     /**
      * Returns the number of entries from a search result.
      *
-     * @link http://php.net/manual/en/function.ldap-count-entries.php
+     * @see http://php.net/manual/en/function.ldap-count-entries.php
      *
-     * @param resource $searchResult
+     * @param resource $searchResults
      *
      * @return int
      */
@@ -81,7 +83,7 @@ class Ldap extends LdapBase
     /**
      * Compare value of attribute found in entry specified with DN.
      *
-     * @link http://php.net/manual/en/function.ldap-compare.php
+     * @see http://php.net/manual/en/function.ldap-compare.php
      *
      * @param string $dn
      * @param string $attribute
@@ -125,7 +127,7 @@ class Ldap extends LdapBase
     /**
      * Get all binary values from the specified result entry.
      *
-     * @link http://php.net/manual/en/function.ldap-get-values-len.php
+     * @see http://php.net/manual/en/function.ldap-get-values-len.php
      *
      * @param $entry
      * @param $attribute
@@ -160,7 +162,7 @@ class Ldap extends LdapBase
     /**
      * Set a callback function to do re-binds on referral chasing.
      *
-     * @link http://php.net/manual/en/function.ldap-set-rebind-proc.php
+     * @see http://php.net/manual/en/function.ldap-set-rebind-proc.php
      *
      * @param callable $callback
      *
@@ -224,9 +226,9 @@ class Ldap extends LdapBase
             $deref,
             $serverControls
         ) {
-            return $this->supportsServerControlsInMethods() && ! empty($serverControls)
-                ? ldap_search($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref, $serverControls)
-                : ldap_search($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref);
+            return empty($serverControls)
+                ? ldap_search($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref)
+                : ldap_search($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref, $serverControls);
         });
     }
 
@@ -245,9 +247,9 @@ class Ldap extends LdapBase
             $deref,
             $serverControls
         ) {
-            return $this->supportsServerControlsInMethods() && ! empty($serverControls)
-                ? ldap_list($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref, $serverControls)
-                : ldap_list($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref);
+            return empty($serverControls)
+                ? ldap_list($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref)
+                : ldap_list($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref, $serverControls);
         });
     }
 
@@ -266,9 +268,9 @@ class Ldap extends LdapBase
             $deref,
             $serverControls
         ) {
-            return $this->supportsServerControlsInMethods() && ! empty($serverControls)
-                ? ldap_read($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref, $serverControls)
-                : ldap_read($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref);
+            return empty($serverControls)
+                ? ldap_read($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref)
+                : ldap_read($this->connection, $dn, $filter, $fields, $onlyAttributes, $size, $time, $deref, $serverControls);
         });
     }
 
@@ -285,9 +287,9 @@ class Ldap extends LdapBase
             &$referrals,
             &$serverControls
         ) {
-            return $this->supportsServerControlsInMethods() && ! empty($serverControls)
-                ? ldap_parse_result($this->connection, $result, $errorCode, $dn, $errorMessage, $referrals, $serverControls)
-                : ldap_parse_result($this->connection, $result, $errorCode, $dn, $errorMessage, $referrals);
+            return empty($serverControls)
+                ? ldap_parse_result($this->connection, $result, $errorCode, $dn, $errorMessage, $referrals)
+                : ldap_parse_result($this->connection, $result, $errorCode, $dn, $errorMessage, $referrals, $serverControls);
         });
     }
 
@@ -419,9 +421,7 @@ class Ldap extends LdapBase
      */
     public function errNo()
     {
-        return $this->connection
-            ? ldap_errno($this->connection)
-            : null;
+        return $this->connection ? ldap_errno($this->connection) : null;
     }
 
     /**
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/LdapInterface.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/LdapInterface.php
index 7a285b88..a1773add 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/LdapInterface.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/LdapInterface.php
@@ -136,9 +136,9 @@ interface LdapInterface
     /**
      * Retrieve the entries from a search result.
      *
-     * @link http://php.net/manual/en/function.ldap-get-entries.php
+     * @see http://php.net/manual/en/function.ldap-get-entries.php
      *
-     * @param resource $searchResult
+     * @param resource $searchResults
      *
      * @return array
      */
@@ -147,7 +147,7 @@ interface LdapInterface
     /**
      * Retrieve the last error on the current connection.
      *
-     * @link http://php.net/manual/en/function.ldap-error.php
+     * @see http://php.net/manual/en/function.ldap-error.php
      *
      * @return string|null
      */
@@ -167,7 +167,7 @@ interface LdapInterface
     /**
      * Set an option on the current connection.
      *
-     * @link http://php.net/manual/en/function.ldap-set-option.php
+     * @see http://php.net/manual/en/function.ldap-set-option.php
      *
      * @param int   $option
      * @param mixed $value
@@ -188,7 +188,7 @@ interface LdapInterface
     /**
      * Get the value for the LDAP option.
      *
-     * @link https://www.php.net/manual/en/function.ldap-get-option.php
+     * @see https://www.php.net/manual/en/function.ldap-get-option.php
      *
      * @param int   $option
      * @param mixed $value
@@ -200,7 +200,7 @@ interface LdapInterface
     /**
      * Starts a connection using TLS.
      *
-     * @link http://php.net/manual/en/function.ldap-start-tls.php
+     * @see http://php.net/manual/en/function.ldap-start-tls.php
      *
      * @throws LdapRecordException
      *
@@ -211,7 +211,7 @@ interface LdapInterface
     /**
      * Connects to the specified hostname using the specified port.
      *
-     * @link http://php.net/manual/en/function.ldap-start-tls.php
+     * @see http://php.net/manual/en/function.ldap-start-tls.php
      *
      * @param string|array $hosts
      * @param int          $port
@@ -225,7 +225,7 @@ interface LdapInterface
      *
      * Returns false if no connection is present.
      *
-     * @link http://php.net/manual/en/function.ldap-close.php
+     * @see http://php.net/manual/en/function.ldap-close.php
      *
      * @return bool
      */
@@ -234,7 +234,7 @@ interface LdapInterface
     /**
      * Performs a search on the current connection.
      *
-     * @link http://php.net/manual/en/function.ldap-search.php
+     * @see http://php.net/manual/en/function.ldap-search.php
      *
      * @param string $dn
      * @param string $filter
@@ -252,11 +252,11 @@ interface LdapInterface
     /**
      * Performs a single level search on the current connection.
      *
-     * @link http://php.net/manual/en/function.ldap-list.php
+     * @see http://php.net/manual/en/function.ldap-list.php
      *
      * @param string $dn
      * @param string $filter
-     * @param array  $attributes
+     * @param array  $fields
      * @param bool   $onlyAttributes
      * @param int    $size
      * @param int    $time
@@ -270,7 +270,7 @@ interface LdapInterface
     /**
      * Reads an entry on the current connection.
      *
-     * @link http://php.net/manual/en/function.ldap-read.php
+     * @see http://php.net/manual/en/function.ldap-read.php
      *
      * @param string $dn
      * @param string $filter
@@ -288,7 +288,7 @@ interface LdapInterface
     /**
      * Extract information from an LDAP result.
      *
-     * @link https://www.php.net/manual/en/function.ldap-parse-result.php
+     * @see https://www.php.net/manual/en/function.ldap-parse-result.php
      *
      * @param resource $result
      * @param int      $errorCode
@@ -305,7 +305,7 @@ interface LdapInterface
      * Binds to the current connection using the specified username and password.
      * If sasl is true, the current connection is bound using SASL.
      *
-     * @link http://php.net/manual/en/function.ldap-bind.php
+     * @see http://php.net/manual/en/function.ldap-bind.php
      *
      * @param string $username
      * @param string $password
@@ -319,7 +319,7 @@ interface LdapInterface
     /**
      * Adds an entry to the current connection.
      *
-     * @link http://php.net/manual/en/function.ldap-add.php
+     * @see http://php.net/manual/en/function.ldap-add.php
      *
      * @param string $dn
      * @param array  $entry
@@ -333,7 +333,7 @@ interface LdapInterface
     /**
      * Deletes an entry on the current connection.
      *
-     * @link http://php.net/manual/en/function.ldap-delete.php
+     * @see http://php.net/manual/en/function.ldap-delete.php
      *
      * @param string $dn
      *
@@ -346,7 +346,7 @@ interface LdapInterface
     /**
      * Modify the name of an entry on the current connection.
      *
-     * @link http://php.net/manual/en/function.ldap-rename.php
+     * @see http://php.net/manual/en/function.ldap-rename.php
      *
      * @param string $dn
      * @param string $newRdn
@@ -362,7 +362,7 @@ interface LdapInterface
     /**
      * Modifies an existing entry on the current connection.
      *
-     * @link http://php.net/manual/en/function.ldap-modify.php
+     * @see http://php.net/manual/en/function.ldap-modify.php
      *
      * @param string $dn
      * @param array  $entry
@@ -376,7 +376,7 @@ interface LdapInterface
     /**
      * Batch modifies an existing entry on the current connection.
      *
-     * @link http://php.net/manual/en/function.ldap-modify-batch.php
+     * @see http://php.net/manual/en/function.ldap-modify-batch.php
      *
      * @param string $dn
      * @param array  $values
@@ -390,7 +390,7 @@ interface LdapInterface
     /**
      * Add attribute values to current attributes.
      *
-     * @link http://php.net/manual/en/function.ldap-mod-add.php
+     * @see http://php.net/manual/en/function.ldap-mod-add.php
      *
      * @param string $dn
      * @param array  $entry
@@ -404,7 +404,7 @@ interface LdapInterface
     /**
      * Replaces attribute values with new ones.
      *
-     * @link http://php.net/manual/en/function.ldap-mod-replace.php
+     * @see http://php.net/manual/en/function.ldap-mod-replace.php
      *
      * @param string $dn
      * @param array  $entry
@@ -418,7 +418,7 @@ interface LdapInterface
     /**
      * Delete attribute values from current attributes.
      *
-     * @link http://php.net/manual/en/function.ldap-mod-del.php
+     * @see http://php.net/manual/en/function.ldap-mod-del.php
      *
      * @param string $dn
      * @param array  $entry
@@ -432,7 +432,7 @@ interface LdapInterface
     /**
      * Send LDAP pagination control.
      *
-     * @link http://php.net/manual/en/function.ldap-control-paged-result.php
+     * @see http://php.net/manual/en/function.ldap-control-paged-result.php
      *
      * @param int    $pageSize
      * @param bool   $isCritical
@@ -445,7 +445,7 @@ interface LdapInterface
     /**
      * Retrieve the LDAP pagination cookie.
      *
-     * @link http://php.net/manual/en/function.ldap-control-paged-result-response.php
+     * @see http://php.net/manual/en/function.ldap-control-paged-result-response.php
      *
      * @param resource $result
      * @param string   $cookie
@@ -457,7 +457,7 @@ interface LdapInterface
     /**
      * Frees up the memory allocated internally to store the result.
      *
-     * @link https://www.php.net/manual/en/function.ldap-free-result.php
+     * @see https://www.php.net/manual/en/function.ldap-free-result.php
      *
      * @param resource $result
      *
@@ -466,10 +466,9 @@ interface LdapInterface
     public function freeResult($result);
 
     /**
-     * Returns the error number of the last command
-     * executed on the current connection.
+     * Returns the error number of the last command executed.
      *
-     * @link http://php.net/manual/en/function.ldap-errno.php
+     * @see http://php.net/manual/en/function.ldap-errno.php
      *
      * @return int|null
      */
@@ -478,7 +477,7 @@ interface LdapInterface
     /**
      * Returns the error string of the specified error number.
      *
-     * @link http://php.net/manual/en/function.ldap-err2str.php
+     * @see http://php.net/manual/en/function.ldap-err2str.php
      *
      * @param int $number
      *
@@ -510,6 +509,8 @@ interface LdapInterface
     /**
      * Determine if the current PHP version supports server controls.
      *
+     * @deprecated since v2.5.0
+     *
      * @return bool
      */
     public function supportsServerControlsInMethods();
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/AccountControl.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/AccountControl.php
index eb1b40dd..9c6240bc 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/AccountControl.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/AccountControl.php
@@ -326,7 +326,7 @@ class AccountControl
      *
      * For information about how to programmatically set this permission, visit the following link:
      *
-     * @link http://msdn2.microsoft.com/en-us/library/aa746398.aspx
+     * @see http://msdn2.microsoft.com/en-us/library/aa746398.aspx
      *
      * @return $this
      */
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedName.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedName.php
index c8af395a..c092173e 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedName.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedName.php
@@ -3,6 +3,7 @@
 namespace LdapRecord\Models\Attributes;
 
 use LdapRecord\EscapesValues;
+use LdapRecord\Support\Arr;
 
 class DistinguishedName
 {
@@ -60,7 +61,7 @@ class DistinguishedName
     }
 
     /**
-     * Make a new Distinguished Name instance.
+     * Make a new distinguished name instance.
      *
      * @param string|null $value
      *
@@ -158,19 +159,15 @@ class DistinguishedName
     }
 
     /**
-     * Get the Distinguished Name values without attributes.
+     * Get the distinguished name values without attributes.
      *
      * @return array
      */
     public function values()
     {
-        $components = $this->components();
-
         $values = [];
 
-        foreach ($components as $rdn) {
-            [,$value] = static::explodeRdn($rdn);
-
+        foreach ($this->multi() as [, $value]) {
             $values[] = static::unescape($value);
         }
 
@@ -178,35 +175,45 @@ class DistinguishedName
     }
 
     /**
-     * Get the Distinguished Name components with attributes.
+     * Get the distinguished name attributes without values.
      *
      * @return array
      */
-    public function components()
+    public function attributes()
     {
-        $rdns = static::explode($this->value);
+        $attributes = [];
 
-        $components = [];
+        foreach ($this->multi() as [$attribute]) {
+            $attributes[] = $attribute;
+        }
 
-        foreach ($rdns as $rdn) {
-            [$attribute, $value] = static::explodeRdn($rdn);
+        return $attributes;
+    }
+
+    /**
+     * Get the distinguished name components with attributes.
+     *
+     * @return array
+     */
+    public function components()
+    {
+        $components = [];
 
-            // When a Distinguished Name is exploded, the values are automatically
+        foreach ($this->multi() as [$attribute, $value]) {
+            // When a distinguished name is exploded, the values are automatically
             // escaped. This cannot be opted out of. Here we will unescape
             // the attribute value, then re-escape it to its original
             // representation from the server using the "dn" flag.
             $value = $this->escape(static::unescape($value))->dn();
 
-            $components[] = static::makeRdn([
-                $attribute, $value,
-            ]);
+            $components[] = static::makeRdn([$attribute, $value]);
         }
 
         return $components;
     }
 
     /**
-     * Convert the DN into an associative array.
+     * Convert the distinguished name into an associative array.
      *
      * @return array
      */
@@ -214,9 +221,7 @@ class DistinguishedName
     {
         $map = [];
 
-        foreach ($this->components() as $rdn) {
-            [$attribute, $value] = static::explodeRdn($rdn);
-
+        foreach ($this->multi() as [$attribute, $value]) {
             $attribute = $this->normalize($attribute);
 
             array_key_exists($attribute, $map)
@@ -228,31 +233,71 @@ class DistinguishedName
     }
 
     /**
-     * Get the name value.
+     * Split the RDNs into a multi-dimensional array.
+     *
+     * @return array
+     */
+    public function multi()
+    {
+        return array_map(function ($rdn) {
+            return static::explodeRdn($rdn);
+        }, $this->rdns());
+    }
+
+    /**
+     * Split the distinguished name into an array of unescaped RDN's.
+     *
+     * @return array
+     */
+    public function rdns()
+    {
+        return static::explode($this->value);
+    }
+
+    /**
+     * Get the first RDNs value.
      *
      * @return string|null
      */
     public function name()
     {
-        $values = $this->values();
+        return Arr::first($this->values());
+    }
 
-        return reset($values) ?: null;
+    /**
+     * Get the first RDNs attribute.
+     *
+     * @return string|null
+     */
+    public function head()
+    {
+        return Arr::first($this->attributes());
     }
 
     /**
-     * Get the relative Distinguished name.
+     * Get the relative distinguished name.
      *
      * @return string|null
      */
     public function relative()
     {
-        $components = $this->components();
+        return Arr::first($this->components());
+    }
 
-        return reset($components) ?: null;
+    /**
+     * Alias of relative().
+     *
+     * Get the first RDN from the distinguished name.
+     *
+     * @return string|null
+     */
+    public function first()
+    {
+        return $this->relative();
     }
 
     /**
-     * Get the parent Distinguished name.
+     * Get the parent distinguished name.
      *
      * @return string|null
      */
@@ -266,7 +311,7 @@ class DistinguishedName
     }
 
     /**
-     * Determine if the current Distinguished Name is a parent of the given child.
+     * Determine if the current distinguished name is a parent of the given child.
      *
      * @param DistinguishedName $child
      *
@@ -278,7 +323,7 @@ class DistinguishedName
     }
 
     /**
-     * Determine if the current Distinguished Name is a child of the given parent.
+     * Determine if the current distinguished name is a child of the given parent.
      *
      * @param DistinguishedName $parent
      *
@@ -299,7 +344,7 @@ class DistinguishedName
     }
 
     /**
-     * Determine if the current Distinguished Name is an ancestor of the descendant.
+     * Determine if the current distinguished name is an ancestor of the descendant.
      *
      * @param DistinguishedName $descendant
      *
@@ -311,7 +356,7 @@ class DistinguishedName
     }
 
     /**
-     * Determine if the current Distinguished Name is a descendant of the ancestor.
+     * Determine if the current distinguished name is a descendant of the ancestor.
      *
      * @param DistinguishedName $ancestor
      *
@@ -336,7 +381,7 @@ class DistinguishedName
     }
 
     /**
-     * Compare whether the two Distinguished Name values are equal.
+     * Compare whether the two distinguished name values are equal.
      *
      * @param array $values
      * @param array $other
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedNameBuilder.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedNameBuilder.php
index 3fda99a5..83dfe716 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedNameBuilder.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/DistinguishedNameBuilder.php
@@ -45,7 +45,7 @@ class DistinguishedNameBuilder
      */
     public function __call($method, $args)
     {
-        return $this->get()->{$method}($args);
+        return $this->get()->{$method}(...$args);
     }
 
     /**
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Guid.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Guid.php
index 34c0248b..d139f5f8 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Guid.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Attributes/Guid.php
@@ -19,7 +19,7 @@ class Guid
      *
      * @author Chad Sikorra <[email protected]>
      *
-     * @link https://github.com/ldaptools/ldaptools
+     * @see https://github.com/ldaptools/ldaptools
      *
      * @var array
      */
@@ -36,7 +36,7 @@ class Guid
      *
      * @author Chad Sikorra <[email protected]>
      *
-     * @link https://github.com/ldaptools/ldaptools
+     * @see https://github.com/ldaptools/ldaptools
      *
      * @var array
      */
@@ -142,7 +142,7 @@ class Guid
      *
      * @author Chad Sikorra <[email protected]>
      *
-     * @link https://github.com/ldaptools/ldaptools
+     * @see https://github.com/ldaptools/ldaptools
      *
      * @param string $hex      The full hex string.
      * @param array  $sections An array of start and length (unless octet is true, then length is always 2).
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasPassword.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasPassword.php
index c2f2dba4..98224566 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasPassword.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HasPassword.php
@@ -185,7 +185,15 @@ trait HasPassword
      */
     protected function validateSecureConnection()
     {
-        if (! $this->getConnection()->getLdapConnection()->canChangePasswords()) {
+        $connection = $this->getConnection();
+
+        if ($connection->isConnected()) {
+            $secure = $connection->getLdapConnection()->canChangePasswords();
+        } else {
+            $secure = $connection->getConfiguration()->get('use_ssl') || $connection->getConfiguration()->get('use_tls');
+        }
+
+        if (! $secure) {
             throw new ConnectionException(
                 'You must be connected to your LDAP server with TLS or SSL to perform this operation.'
             );
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HidesAttributes.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HidesAttributes.php
index 34427aea..9cc21005 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HidesAttributes.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Concerns/HidesAttributes.php
@@ -5,7 +5,7 @@ namespace LdapRecord\Models\Concerns;
 /**
  * @author Taylor Otwell
  *
- * @link https://laravel.com
+ * @see https://laravel.com
  */
 trait HidesAttributes
 {
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Model.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Model.php
index 2818308e..6ba24b45 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Model.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Model.php
@@ -767,6 +767,18 @@ abstract class Model implements ArrayAccess, JsonSerializable
         return $this->newDn($dn ?? $this->dn)->name();
     }
 
+    /**
+     * Get the head attribute of the model, or the given DN.
+     *
+     * @param string|null $dn
+     *
+     * @return string|null
+     */
+    public function getHead($dn = null)
+    {
+        return $this->newDn($dn ?? $this->dn)->head();
+    }
+
     /**
      * Get the RDN of the model, of the given DN.
      *
@@ -803,10 +815,20 @@ abstract class Model implements ArrayAccess, JsonSerializable
         return new DistinguishedName($dn);
     }
 
+    /**
+     * Get the model's object GUID key.
+     *
+     * @return void
+     */
+    public function getObjectGuidKey()
+    {
+        return $this->guidKey;
+    }
+
     /**
      * Get the model's binary object GUID.
      *
-     * @link https://msdn.microsoft.com/en-us/library/ms679021(v=vs.85).aspx
+     * @see https://msdn.microsoft.com/en-us/library/ms679021(v=vs.85).aspx
      *
      * @return string|null
      */
@@ -952,8 +974,8 @@ abstract class Model implements ArrayAccess, JsonSerializable
     protected function performInsert()
     {
         // Here we will populate the models object classes if it
-        // does not already have any. An LDAP object cannot
-        // be successfully created without them set.
+        // does not already have any set. An LDAP object cannot
+        // be successfully created in the server without them.
         if (! $this->hasAttribute('objectclass')) {
             $this->setAttribute('objectclass', static::$objectClasses);
         }
@@ -961,17 +983,18 @@ abstract class Model implements ArrayAccess, JsonSerializable
         $query = $this->newQuery();
 
         // If the model does not currently have a distinguished
-        // name, we will attempt to create one automatically
-        // using the current query builders DN as a base.
+        // name, we will attempt to generate one automatically
+        // using the current query builder's DN as the base.
         if (empty($this->getDn())) {
             $this->setDn($this->getCreatableDn());
         }
 
         $this->fireModelEvent(new Events\Creating($this));
 
-        // Here we perform the insert of the object in the directory.
-        // We will also filter out any empty attribute values here,
-        // otherwise the LDAP server will return an error message.
+        // Here we perform the insert of new object in the directory,
+        // but filter out any empty attributes before sending them
+        // to the server. LDAP servers will throw an exception if
+        // attributes have been given empty or null values.
         $query->insert($this->getDn(), array_filter($this->getAttributes()));
 
         $this->fireModelEvent(new Events\Created($this));
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/HasMany.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/HasMany.php
index 1cc582d5..d8dfa08c 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/HasMany.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/HasMany.php
@@ -2,6 +2,7 @@
 
 namespace LdapRecord\Models\Relations;
 
+use Closure;
 use LdapRecord\DetectsErrors;
 use LdapRecord\LdapRecordException;
 use LdapRecord\Models\Model;
@@ -107,6 +108,21 @@ class HasMany extends OneToMany
         return $result;
     }
 
+    /**
+     * Chunk the relation results using the given callback.
+     *
+     * @param int     $pageSize
+     * @param Closure $callback
+     *
+     * @return void
+     */
+    public function chunk($pageSize, Closure $callback)
+    {
+        $this->getRelationQuery()->chunk($pageSize, function ($entries) use ($callback) {
+            $callback($this->transformResults($entries));
+        });
+    }
+
     /**
      * Get the relationships results.
      *
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/OneToMany.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/OneToMany.php
index b550300f..d0a407cc 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/OneToMany.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Relations/OneToMany.php
@@ -89,7 +89,7 @@ abstract class OneToMany extends Relation
     public function getResults()
     {
         $results = $this->recursive
-            ? $this->getRecursiveResults($this->getRelationResults())
+            ? $this->getRecursiveResults()
             : $this->getRelationResults();
 
         return $results->merge(
@@ -142,46 +142,45 @@ abstract class OneToMany extends Relation
     /**
      * Get the results for the models relation recursively.
      *
-     * @param Collection $models The models to retrieve nested relation results from
-     * @param string[]   $loaded The distinguished names of models already loaded
+     * @param string[] $loaded The distinguished names of models already loaded
      *
      * @return Collection
      */
-    protected function getRecursiveResults(Collection $models, array &$loaded = [])
+    protected function getRecursiveResults(array $loaded = [])
     {
-        return $models->unless(empty($loaded), function ($models) use ($loaded) {
+        $results = $this->getRelationResults()->reject(function (Model $model) use ($loaded) {
             // Here we will exclude the models that we have already
-            // gathered the recursive results for so we don't run
+            // loaded the recursive results for so we don't run
             // into issues with circular relations in LDAP.
-            return $models->reject(function (Model $model) use ($loaded) {
-                return in_array($model->getDn(), $loaded);
-            });
-        })->each(function (Model $model) use (&$loaded, $models) {
+            return in_array($model->getDn(), $loaded);
+        });
+
+        foreach ($results as $model) {
             $loaded[] = $model->getDn();
 
-            // Next, we will call the same relation method on each
-            // returned model to retrieve its related models and
-            // merge them into our final resulting collection.
-            $this->getRecursiveResults(
-                $this->getRecursiveRelationResults($model),
-                $loaded
-            )->each(function (Model $related) use ($models) {
-                $models->add($related);
-            });
-        });
+            // Finally, we will fetch the related models relations,
+            // passing along our loaded models, to ensure we do
+            // not attempt fetching already loaded relations.
+            $results = $results->merge(
+                $this->getRecursiveRelationResults($model, $loaded)
+            );
+        }
+
+        return $results;
     }
 
     /**
      * Get the recursive relation results for given model.
      *
      * @param Model $model
+     * @param array $loaded
      *
      * @return Collection
      */
-    protected function getRecursiveRelationResults(Model $model)
+    protected function getRecursiveRelationResults(Model $model, array $loaded)
     {
         return method_exists($model, $this->relationName)
-            ? $model->{$this->relationName}()->recursive()->get()
+            ? $model->{$this->relationName}()->getRecursiveResults($loaded)
             : $model->newCollection();
     }
 }
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/ActiveDirectory.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/ActiveDirectory.php
index 73d6e8ce..61d21ef2 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/ActiveDirectory.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Models/Types/ActiveDirectory.php
@@ -14,7 +14,7 @@ interface ActiveDirectory extends TypeInterface
     /**
      * Returns the model's hex object SID.
      *
-     * @link https://msdn.microsoft.com/en-us/library/ms679024(v=vs.85).aspx
+     * @see https://msdn.microsoft.com/en-us/library/ms679024(v=vs.85).aspx
      *
      * @return string
      */
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/ArrayCacheStore.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/ArrayCacheStore.php
index 2cf00ff9..d7480a7b 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/ArrayCacheStore.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/ArrayCacheStore.php
@@ -44,12 +44,36 @@ class ArrayCacheStore implements CacheInterface
     {
         $this->storage[$key] = [
             'value' => $value,
-            'expiresAt' => $this->parseDateInterval($ttl),
+            'expiresAt' => $this->calculateExpiration($ttl),
         ];
 
         return true;
     }
 
+    /**
+     * Get the expiration time of the key.
+     *
+     * @param int $seconds
+     *
+     * @return int
+     */
+    protected function calculateExpiration($seconds)
+    {
+        return $this->toTimestamp($seconds);
+    }
+
+    /**
+     * Get the UNIX timestamp for the given number of seconds.
+     *
+     * @param int $seconds
+     *
+     * @return int
+     */
+    protected function toTimestamp($seconds)
+    {
+        return $seconds > 0 ? $this->availableAt($seconds) : 0;
+    }
+
     /**
      * @inheritdoc
      */
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Cache.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Cache.php
index b9a7656a..dfbf8cd2 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Cache.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Cache.php
@@ -51,7 +51,13 @@ class Cache
      */
     public function put($key, $value, $ttl = null)
     {
-        return $this->store->set($key, $value, $this->expiresAt($ttl));
+        $seconds = $this->secondsUntil($ttl);
+
+        if ($seconds <= 0) {
+            return $this->delete($key);
+        }
+
+        return $this->store->set($key, $value, $seconds);
     }
 
     /**
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/InteractsWithTime.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/InteractsWithTime.php
index f802b32f..1562ec0a 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/InteractsWithTime.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/InteractsWithTime.php
@@ -9,18 +9,34 @@ use DateTimeInterface;
 /**
  * @author Taylor Otwell
  *
- * @link https://laravel.com
+ * @see https://laravel.com
  */
 trait InteractsWithTime
 {
     /**
-     * Get the "expires at" UNIX timestamp.
+     * Get the number of seconds until the given DateTime.
      *
      * @param DateTimeInterface|DateInterval|int $delay
      *
      * @return int
      */
-    protected function expiresAt($delay = 0)
+    protected function secondsUntil($delay)
+    {
+        $delay = $this->parseDateInterval($delay);
+
+        return $delay instanceof DateTimeInterface
+            ? max(0, $delay->getTimestamp() - $this->currentTime())
+            : (int) $delay;
+    }
+
+    /**
+     * Get the "available at" UNIX timestamp.
+     *
+     * @param DateTimeInterface|DateInterval|int $delay
+     *
+     * @return int
+     */
+    protected function availableAt($delay = 0)
     {
         $delay = $this->parseDateInterval($delay);
 
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/DeprecatedPaginator.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/DeprecatedPaginator.php
index 7367f030..b4a7f8db 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/DeprecatedPaginator.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Query/Pagination/DeprecatedPaginator.php
@@ -5,7 +5,7 @@ namespace LdapRecord\Query\Pagination;
 use LdapRecord\LdapInterface;
 
 /**
- * @deprecated
+ * @deprecated since v2.5.0
  */
 class DeprecatedPaginator extends AbstractPaginator
 {
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/ConnectionFake.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/ConnectionFake.php
index 9d46a8a3..0aa12a1e 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/ConnectionFake.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/ConnectionFake.php
@@ -32,7 +32,11 @@ class ConnectionFake extends Connection
      */
     public static function make(array $config = [], $ldap = LdapFake::class)
     {
-        return new static($config, new $ldap());
+        $connection = new static($config, new $ldap());
+
+        $connection->configure();
+
+        return $connection;
     }
 
     /**
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/LdapExpectation.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/LdapExpectation.php
index f6979b55..90a5fa2e 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/LdapExpectation.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/LdapExpectation.php
@@ -207,7 +207,7 @@ class LdapExpectation
     public function getMethod()
     {
         if (is_null($this->method)) {
-            throw new UnexpectedValueException('The [$method] property cannot be null.');
+            throw new UnexpectedValueException('An expectation must have a method.');
         }
 
         return $this->method;
@@ -226,7 +226,7 @@ class LdapExpectation
     /**
      * Get the expected arguments.
      *
-     * @return array
+     * @return Constraint[]
      */
     public function getExpectedArgs()
     {
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/LdapFake.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/LdapFake.php
index 56b6c656..7ba0e153 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/LdapFake.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Testing/LdapFake.php
@@ -4,13 +4,17 @@ namespace LdapRecord\Testing;
 
 use Exception;
 use LdapRecord\DetailedError;
-use LdapRecord\LdapBase;
+use LdapRecord\DetectsErrors;
+use LdapRecord\HandlesConnection;
+use LdapRecord\LdapInterface;
 use LdapRecord\Support\Arr;
 use PHPUnit\Framework\Assert as PHPUnit;
 use PHPUnit\Framework\Constraint\Constraint;
 
-class LdapFake extends LdapBase
+class LdapFake implements LdapInterface
 {
+    use HandlesConnection, DetectsErrors;
+
     /**
      * The expectations of the LDAP fake.
      *
@@ -101,7 +105,7 @@ class LdapFake extends LdapBase
      *
      * @return bool
      */
-    protected function hasExpectations($method)
+    public function hasExpectations($method)
     {
         return count($this->getExpectations($method)) > 0;
     }
@@ -113,7 +117,7 @@ class LdapFake extends LdapBase
      *
      * @return LdapExpectation[]|mixed
      */
-    protected function getExpectations($method)
+    public function getExpectations($method)
     {
         return $this->expectations[$method] ?? [];
     }
@@ -126,7 +130,7 @@ class LdapFake extends LdapBase
      *
      * @return void
      */
-    protected function removeExpectation($method, $key)
+    public function removeExpectation($method, $key)
     {
         unset($this->expectations[$method][$key]);
     }
@@ -230,7 +234,7 @@ class LdapFake extends LdapBase
     {
         return $this->hasExpectations('isUsingSSL')
             ? $this->resolveExpectation('isUsingSSL')
-            : parent::isUsingSSL();
+            : $this->useSSL;
     }
 
     /**
@@ -240,7 +244,7 @@ class LdapFake extends LdapBase
     {
         return $this->hasExpectations('isUsingTLS')
             ? $this->resolveExpectation('isUsingTLS')
-            : parent::isUsingTLS();
+            : $this->useTLS;
     }
 
     /**
@@ -250,7 +254,7 @@ class LdapFake extends LdapBase
     {
         return $this->hasExpectations('isBound')
             ? $this->resolveExpectation('isBound')
-            : parent::isBound();
+            : $this->bound;
     }
 
     /**
@@ -453,7 +457,7 @@ class LdapFake extends LdapBase
      *
      * @return mixed
      */
-    protected function resolveExpectation($method, $args = [])
+    protected function resolveExpectation($method, array $args = [])
     {
         foreach ($this->getExpectations($method) as $key => $expectation) {
             $this->assertMethodArgumentsMatch($method, $expectation->getExpectedArgs(), $args);
@@ -501,7 +505,7 @@ class LdapFake extends LdapBase
      *
      * @return void
      */
-    protected function assertMethodArgumentsMatch($method, $expectedArgs = [], $methodArgs = [])
+    protected function assertMethodArgumentsMatch($method, array $expectedArgs = [], array $methodArgs = [])
     {
         foreach ($expectedArgs as $key => $constraint) {
             $argNumber = $key + 1;
diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Utilities.php b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Utilities.php
index f95aa263..0f0ca3c7 100644
--- a/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Utilities.php
+++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/src/Utilities.php
@@ -55,8 +55,8 @@ class Utilities
      *
      * @author Chad Sikorra
      *
-     * @link https://github.com/ChadSikorra
-     * @link https://stackoverflow.com/questions/39533560/php-ldap-get-user-sid
+     * @see https://github.com/ChadSikorra
+     * @see https://stackoverflow.com/questions/39533560/php-ldap-get-user-sid
      *
      * @param string $value The Binary SID
      *
diff --git a/data/web/inc/lib/vendor/illuminate/contracts/Support/MessageBag.php b/data/web/inc/lib/vendor/illuminate/contracts/Support/MessageBag.php
index 78bd8a00..7f708aca 100644
--- a/data/web/inc/lib/vendor/illuminate/contracts/Support/MessageBag.php
+++ b/data/web/inc/lib/vendor/illuminate/contracts/Support/MessageBag.php
@@ -2,7 +2,9 @@
 
 namespace Illuminate\Contracts\Support;
 
-interface MessageBag extends Arrayable
+use Countable;
+
+interface MessageBag extends Arrayable, Countable
 {
     /**
      * Get the keys present in the message bag.
@@ -97,11 +99,4 @@ interface MessageBag extends Arrayable
      * @return bool
      */
     public function isNotEmpty();
-
-    /**
-     * Get the number of messages in the container.
-     *
-     * @return int
-     */
-    public function count();
 }
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/composer.json b/data/web/inc/lib/vendor/nesbot/carbon/composer.json
index 29fb08d9..d0cadc9c 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/composer.json
+++ b/data/web/inc/lib/vendor/nesbot/carbon/composer.json
@@ -7,30 +7,24 @@
         "time",
         "DateTime"
     ],
-    "homepage": "http://carbon.nesbot.com",
-    "support": {
-        "issues": "https://github.com/briannesbitt/Carbon/issues",
-        "source": "https://github.com/briannesbitt/Carbon"
-    },
+    "homepage": "https://carbon.nesbot.com",
     "license": "MIT",
     "authors": [
         {
             "name": "Brian Nesbitt",
             "email": "[email protected]",
-            "homepage": "http://nesbot.com"
+            "homepage": "https://markido.com"
         },
         {
             "name": "kylekatarnls",
-            "homepage": "http://github.com/kylekatarnls"
+            "homepage": "https://github.com/kylekatarnls"
         }
     ],
-    "prefer-stable": true,
-    "minimum-stability": "dev",
-    "bin": ["bin/carbon"],
     "require": {
         "php": "^7.1.8 || ^8.0",
         "ext-json": "*",
         "symfony/polyfill-mbstring": "^1.0",
+        "symfony/polyfill-php80": "^1.16",
         "symfony/translation": "^3.4 || ^4.0 || ^5.0"
     },
     "require-dev": {
@@ -43,43 +37,14 @@
         "phpunit/phpunit": "^7.5.20 || ^8.5.14",
         "squizlabs/php_codesniffer": "^3.4"
     },
-    "autoload": {
-        "psr-4": {
-            "Carbon\\": "src/Carbon/"
-        }
-    },
-    "autoload-dev": {
-        "files": [
-            "tests/Laravel/ServiceProvider.php"
-        ],
-        "psr-4": {
-            "Tests\\": "tests/"
-        }
-    },
     "config": {
         "process-timeout": 0,
         "sort-packages": true
     },
-    "scripts": {
-        "test": [
-            "@phpunit",
-            "@style-check"
-        ],
-        "style-check": [
-            "@phpcs",
-            "@phpstan",
-            "@phpmd"
-        ],
-        "phpunit": "phpunit --verbose",
-        "phpcs": "php-cs-fixer fix -v --diff --dry-run",
-        "phpstan": "phpstan analyse --configuration phpstan.neon",
-        "phpmd": "phpmd src text /phpmd.xml",
-        "phpdoc": "php phpdoc.php"
-    },
     "extra": {
         "branch-alias": {
-            "dev-master": "2.x-dev",
-            "dev-3.x": "3.x-dev"
+            "dev-3.x": "3.x-dev",
+            "dev-master": "2.x-dev"
         },
         "laravel": {
             "providers": [
@@ -91,5 +56,43 @@
                 "extension.neon"
             ]
         }
+    },
+    "autoload": {
+        "psr-4": {
+            "Carbon\\": "src/Carbon/"
+        }
+    },
+    "autoload-dev": {
+        "psr-4": {
+            "Tests\\": "tests/"
+        },
+        "files": [
+            "tests/Laravel/ServiceProvider.php"
+        ]
+    },
+    "minimum-stability": "dev",
+    "prefer-stable": true,
+    "bin": [
+        "bin/carbon"
+    ],
+    "scripts": {
+        "phpcs": "php-cs-fixer fix -v --diff --dry-run",
+        "phpdoc": "php phpdoc.php",
+        "phpmd": "phpmd src text /phpmd.xml",
+        "phpstan": "phpstan analyse --configuration phpstan.neon",
+        "phpunit": "phpunit --verbose",
+        "style-check": [
+            "@phpcs",
+            "@phpstan",
+            "@phpmd"
+        ],
+        "test": [
+            "@phpunit",
+            "@style-check"
+        ]
+    },
+    "support": {
+        "issues": "https://github.com/briannesbitt/Carbon/issues",
+        "source": "https://github.com/briannesbitt/Carbon"
     }
 }
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/contributing.md b/data/web/inc/lib/vendor/nesbot/carbon/contributing.md
deleted file mode 100644
index d2bedac5..00000000
--- a/data/web/inc/lib/vendor/nesbot/carbon/contributing.md
+++ /dev/null
@@ -1,154 +0,0 @@
-# Contributing to Carbon
-
-## Issue Contributions
-
-Please report any security issue using [Tidelift security contact](https://tidelift.com/security).
-Tidelift will coordinate the fix and disclosure.
-Please don't disclose security bugs publicly until they have been handled by us.
-
-For any other bug or issue, please click this link and follow the template:
-[Create new issue](https://github.com/briannesbitt/Carbon/issues/new)
-
-You may think this template does not apply to your case but please think again. A long description will never be as
-clear as a code chunk with the output you expect from it (for either bug report or new features).
-
-## Code Contributions
-
-### Where to begin
-
-We use the label **good first issue** to tag issues that could be a good fit for new contributors, see if there are such issues now following this link:
-
-https://github.com/briannesbitt/Carbon/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22
-
-Else, check the roadmap to see what we plan to do in next releases:
-
-https://github.com/briannesbitt/Carbon/issues/1681
-
-### Develop locally, then submit changes
-
-Fork the [GitHub project](https://github.com/briannesbitt/Carbon) and download it locally:
-
-```shell
-git clone https://github.com/<username>/Carbon.git
-cd Carbon
-git remote add upstream https://github.com/briannesbitt/Carbon.git
-```
-Replace `<username>` with your GitHub username.
-
-Then, you can work on the master or create a specific branch for your development:
-
-```shell
-git checkout -b my-feature-branch -t origin/master
-```
-
-You can now edit the "Carbon" directory contents.
-
-Before committing, please set your name and your e-mail (use the same e-mail address as in your GitHub account):
-
-```shell
-git config --global user.name "Your Name"
-git config --global user.email "[email protected]"
-```
-
-The ```--global``` argument will apply this setting for all your git repositories, remove it to set only your Carbon
-fork with those settings.
-
-Now you can commit your modifications as you usually do with git:
-
-```shell
-git add --all
-git commit -m "The commit message log"
-```
-
-If your patch fixes an open issue, please insert ```#``` immediately followed by the issue number:
-
-```shell
-git commit -m "#21 Fix this or that"
-```
-
-Use git rebase (not git merge) to sync your work from time to time:
-
-```shell
-git fetch origin
-git rebase origin/master
-```
-
-Please add some tests for bug fixes and features (so it will ensure next developments will not break your code),
-then check all is right with phpunit:
-
-Install PHP if you haven't yet, then install composer:
-https://getcomposer.org/download/
-
-Update dependencies:
-```
-./composer.phar update
-```
-
-Or if you installed composer globally:
-```
-composer update
-```
-
-Then call phpunit:
-```
-./vendor/bin/phpunit
-```
-
-Make sure all tests succeed before submitting your pull-request, else we will not be able to merge it.
-
-Push your work on your remote GitHub fork with:
-```
-git push origin my-feature-branch
-```
-
-Go to https://github.com/yourusername/Carbon and select your feature branch. Click the 'Pull Request' button and fill
-out the form.
-
-We will review it within a few days. And we thank you in advance for your help.
-
-## Versioning
-
-### Note about Semantic Versioning and breaking changes
-
-As a developer, you must understand every change is a breaking change. What is a bug for someone
-is expected in someone else's workflow. The consequence of a change strongly depends on the usage.
-[Semantic Versioning](https://semver.org/) relies to public API. In PHP, the public API of a class is its public
-methods. However, if you extend a class, you can access protected methods, then if you use reflexion, you can
-access private methods. So anything can become a public API if you force it to be. That doesn't mean we should handle
-any possible usage, else we would have to publish a major release for each change and it would no longer make sense.
-
-So before any complain about a breaking change, be warned, we do not guarantee a strict Semantic Versioning as you
-may expect, we're following a pragmatic interpretation of Semantic Versioning that allows the software to evolve in a
-reliable way with reasonable maintenance effort.
-
-Concretely, we consider a change as breaking if it makes fail one of our unit test. We will do our best to avoid
-incompatibilities with libraries that extends Carbon classes (such as Laravel that is continuously tested thanks to
-Travis CI, [see the compatibility matrix](https://github.com/kylekatarnls/carbon-laravel/tree/master#carbon-1-dev-version-1next)).
-
-If you're the owner of a library that strongly depends on Carbon, we recommend you to run unit tests daily requiring
-`"nesbot/carbon": "dev-master"` (for `^2`) or `"nesbot/carbon": "dev-version-1.next"` (for `^1`), this way you can
-detect incompatibilities earlier and report it to us before we tag a release. We'll pay attention and try to fix it to
-make update to next minor releases as soft as possible.
-
-We reserve the right to publish emergency patches within 24 hours after a release if a tag that does not respect
-this pattern would have been released despite our vigilance. In this very rare and particular case, we would mark the
-tag as broken on GitHub and backward compatibility would be based on previous stable tag.
-
-Last, you must understand that Carbon extends PHP natives classes, that means Carbon can be impacted by any change
-that occurs in the date/time API of PHP. We watch new PHP versions and handle those changes as quickly as possible
-when detected, but as PHP does not follow the semantic versioning pattern, it basically means any releases (including
-patches) can have unexpected consequences on Carbon methods results.
-
-### Long term support
-
-To benefit the better support, require Carbon using major version range (`^1` or `^2`). By requiring `1.26.*`,
-`~1.26.0` or limited range such as `>=1.20 <1.33`, you fall to low priority support (only security and critical issues
-will be fixed), our prior support goes to next minor releases of each major version. It applies to bug fixes and
-low-cost features. Other new features will only be added in the last stable release. At the opposite, we recommend you
-to restrain to a major number, as there is no compatibility guarantee from a major version to the next. It means
-requiring `>=2`, as it allows any newer version, will probably leads to errors on releasing our next major version.
-
-Open milestones can be patched if a minor bug is detected while if you're on a closed milestone, we'll more likely
-ask you to update first to an open one. See currently open milestones: 
-
-https://github.com/briannesbitt/Carbon/milestones
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/phpmd.xml b/data/web/inc/lib/vendor/nesbot/carbon/phpmd.xml
deleted file mode 100644
index 6f08b294..00000000
--- a/data/web/inc/lib/vendor/nesbot/carbon/phpmd.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-<?xml version="1.0"?>
-<ruleset name="Mess detection rules for Carbon"
-         xmlns="http://pmd.sf.net/ruleset/1.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0
-                     http://pmd.sf.net/ruleset_xml_schema.xsd"
-         xsi:noNamespaceSchemaLocation="
-                     http://pmd.sf.net/ruleset_xml_schema.xsd">
-    <description>
-        Mess detection rules for Carbon
-    </description>
-    <rule ref="rulesets/codesize.xml">
-        <exclude name="CyclomaticComplexity" />
-        <exclude name="NPathComplexity" />
-        <exclude name="ExcessiveMethodLength" />
-        <exclude name="ExcessiveClassLength" />
-        <exclude name="ExcessivePublicCount" />
-        <exclude name="TooManyMethods" />
-        <exclude name="TooManyPublicMethods" />
-        <exclude name="ExcessiveClassComplexity" />
-    </rule>
-    <rule ref="rulesets/cleancode.xml">
-        <exclude name="BooleanArgumentFlag" />
-        <exclude name="StaticAccess" />
-        <exclude name="IfStatementAssignment" />
-        <exclude name="UndefinedVariable" />
-        <exclude name="ErrorControlOperator" />
-    </rule>
-    <rule ref="rulesets/controversial.xml" />
-    <rule ref="rulesets/design.xml">
-        <exclude name="EvalExpression" />
-        <exclude name="CouplingBetweenObjects" />
-        <exclude name="CountInLoopExpression" />
-    </rule>
-    <rule ref="rulesets/design.xml/CouplingBetweenObjects">
-        <properties>
-            <property name="maximum" value="25" />
-        </properties>
-    </rule>
-    <rule ref="rulesets/naming.xml/ShortVariable">
-        <properties>
-            <property name="exceptions" value="ci,id,to,tz" />
-        </properties>
-    </rule>
-    <rule ref="rulesets/unusedcode.xml" />
-</ruleset>
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/readme.md b/data/web/inc/lib/vendor/nesbot/carbon/readme.md
index 0852b3ae..70279c1e 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/readme.md
+++ b/data/web/inc/lib/vendor/nesbot/carbon/readme.md
@@ -8,7 +8,7 @@
 [![PHPStan](https://img.shields.io/badge/PHPStan-enabled-44CC11.svg?longCache=true&style=flat-square)](https://github.com/phpstan/phpstan)
 [![Tidelift](https://tidelift.com/badges/github/briannesbitt/Carbon)](https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme)
 
-An international PHP extension for DateTime. [http://carbon.nesbot.com](http://carbon.nesbot.com)
+An international PHP extension for DateTime. [https://carbon.nesbot.com](https://carbon.nesbot.com)
 
 ```php
 <?php
@@ -84,7 +84,7 @@ printf("Now: %s", Carbon::now());
 
 ### Without Composer
 
-Why are you not using [composer](http://getcomposer.org/)? Download the Carbon [latest release](https://github.com/briannesbitt/Carbon/releases) and put the contents of the ZIP archive into a directory in your project. Then require the file `autoload.php` to get all classes and dependencies loaded on need.
+Why are you not using [composer](https://getcomposer.org/)? Download the Carbon [latest release](https://github.com/briannesbitt/Carbon/releases) and put the contents of the ZIP archive into a directory in your project. Then require the file `autoload.php` to get all classes and dependencies loaded on need.
 
 ```php
 <?php
@@ -97,7 +97,7 @@ printf("Now: %s", Carbon::now());
 
 ## Docs
 
-[http://carbon.nesbot.com/docs](http://carbon.nesbot.com/docs)
+[https://carbon.nesbot.com/docs](https://carbon.nesbot.com/docs)
 
 ## Security contact information
 
@@ -122,7 +122,7 @@ This project exists thanks to all the people who contribute.
 Support this project by becoming a sponsor. Your logo will show up here with a link to your website.
 
 <a href="https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme" target="_blank"><img src="https://carbon.nesbot.com/tidelift-brand.png" width="256" height="64"></a>
-<a href="https://onlinecasinohex.ca/?utm_source=opencollective&amp;utm_medium=github&amp;utm_campaign=Carbon" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/0/avatar.svg" width="192" height="64"></a>
+<a href="https://onlinecasinohex.ca/?utm_source=opencollective&amp;utm_medium=github&amp;utm_campaign=Carbon" target="_blank"><img src="https://images.opencollective.com/hexcasinoca/2da3af2/logo/256.png" width="85" height="64"></a>
 <a href="https://opencollective.com/Carbon/sponsor/0/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/0/avatar.svg"></a>
 <a href="https://opencollective.com/Carbon/sponsor/1/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/1/avatar.svg"></a>
 <a href="https://opencollective.com/Carbon/sponsor/2/website" target="_blank"><img src="https://opencollective.com/Carbon/sponsor/2/avatar.svg"></a>
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonImmutable.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonImmutable.php
index a6750a12..cb1c4988 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonImmutable.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonImmutable.php
@@ -555,6 +555,11 @@ class CarbonImmutable extends DateTimeImmutable implements CarbonInterface
             return 145261681241552;
         }
 
+        // Remove if https://bugs.php.net/bug.php?id=81107 is fixed
+        if (version_compare(PHP_VERSION, '8.1.0-dev', '>=')) {
+            return 1118290769066902787;
+        }
+
         return PHP_INT_MAX;
     }
 
@@ -567,6 +572,11 @@ class CarbonImmutable extends DateTimeImmutable implements CarbonInterface
             return -135908816449551;
         }
 
+        // Remove if https://bugs.php.net/bug.php?id=81107 is fixed
+        if (version_compare(PHP_VERSION, '8.1.0-dev', '>=')) {
+            return -1118290769066898816;
+        }
+
         return max(PHP_INT_MIN, -9223372036854773760);
     }
 }
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonInterface.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonInterface.php
index 7aa1df4c..8f095072 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonInterface.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonInterface.php
@@ -26,6 +26,7 @@ use DateTimeInterface;
 use DateTimeZone;
 use JsonSerializable;
 use ReflectionException;
+use ReturnTypeWillChange;
 use Throwable;
 
 /**
@@ -721,6 +722,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
      *
      * @return static
      */
+    #[ReturnTypeWillChange]
     public static function __set_state($dump);
 
     /**
@@ -755,6 +757,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
      *
      * @return static
      */
+    #[ReturnTypeWillChange]
     public function add($unit, $value = 1, $overflow = null);
 
     /**
@@ -830,6 +833,16 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
      */
     public function average($date = null);
 
+    /**
+     * Clone the current instance if it's mutable.
+     *
+     * This method is convenient to ensure you don't mutate the initial object
+     * but avoid to make a useless copy of it if it's already immutable.
+     *
+     * @return static
+     */
+    public function avoidMutation();
+
     /**
      * Determines if the instance is between two others.
      *
@@ -1066,6 +1079,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
      *
      * @return static|false
      */
+    #[ReturnTypeWillChange]
     public static function createFromFormat($format, $time, $tz = null);
 
     /**
@@ -1946,7 +1960,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
 
     /**
      * Format the instance with the current locale.  You can set the current
-     * locale using setlocale() http://php.net/setlocale.
+     * locale using setlocale() https://php.net/setlocale.
      *
      * @param string $format
      *
@@ -2135,6 +2149,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
     /**
      * {@inheritdoc}
      */
+    #[ReturnTypeWillChange]
     public static function getLastErrors();
 
     /**
@@ -3007,6 +3022,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
      *
      * @return array|string
      */
+    #[ReturnTypeWillChange]
     public function jsonSerialize();
 
     /**
@@ -3317,6 +3333,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
      *
      * @see https://php.net/manual/en/datetime.modify.php
      */
+    #[ReturnTypeWillChange]
     public function modify($modify);
 
     /**
@@ -3700,6 +3717,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
      *
      * @return static
      */
+    #[ReturnTypeWillChange]
     public function setDate($year, $month, $day);
 
     /**
@@ -3764,6 +3782,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
      *
      * @return static
      */
+    #[ReturnTypeWillChange]
     public function setISODate($year, $week, $day = 1);
 
     /**
@@ -3834,6 +3853,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
      *
      * @return static
      */
+    #[ReturnTypeWillChange]
     public function setTime($hour, $minute, $second = 0, $microseconds = 0);
 
     /**
@@ -3863,6 +3883,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
      *
      * @return static
      */
+    #[ReturnTypeWillChange]
     public function setTimestamp($unixTimestamp);
 
     /**
@@ -3872,6 +3893,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
      *
      * @return static
      */
+    #[ReturnTypeWillChange]
     public function setTimezone($value);
 
     /**
@@ -4213,6 +4235,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
      *
      * @return static
      */
+    #[ReturnTypeWillChange]
     public function sub($unit, $value = 1, $overflow = null);
 
     public function subRealUnit($unit, $value = 1);
@@ -4751,7 +4774,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
      *
      * @param string                                             $key
      * @param array                                              $parameters
-     * @param null                                               $number
+     * @param string|int|float|null                              $number
      * @param \Symfony\Component\Translation\TranslatorInterface $translator
      *
      * @return string
@@ -4808,7 +4831,7 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
     public static function translateWith(\Symfony\Component\Translation\TranslatorInterface $translator, string $key, array $parameters = [], $number = null): string;
 
     /**
-     * Format as ->format() do (using date replacements patterns from http://php.net/manual/fr/function.date.php)
+     * Format as ->format() do (using date replacements patterns from https://php.net/manual/en/function.date.php)
      * but translate words whenever possible (months, day names, etc.) using the current locale.
      *
      * @param string $format
@@ -4991,6 +5014,8 @@ interface CarbonInterface extends DateTimeInterface, JsonSerializable
      *
      * @param Closure|static|string|false|null $testNow real or mock Carbon instance
      * @param Closure|null $callback
+     *
+     * @return mixed
      */
     public static function withTestNow($testNow = null, $callback = null);
 
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonInterval.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonInterval.php
index 8801c751..7168fa4b 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonInterval.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonInterval.php
@@ -353,7 +353,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
 
         $spec = $years;
 
-        if (!\is_string($spec) || \floatval($years) || preg_match('/^[0-9.]/', $years)) {
+        if (!\is_string($spec) || (float) $years || preg_match('/^[0-9.]/', $years)) {
             $spec = static::PERIOD_PREFIX;
 
             $spec .= $years > 0 ? $years.static::PERIOD_YEARS : '';
@@ -380,7 +380,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
 
         parent::__construct($spec);
 
-        if (!\is_null($microseconds)) {
+        if ($microseconds !== null) {
             $this->f = $microseconds / Carbon::MICROSECONDS_PER_SECOND;
         }
     }
@@ -536,7 +536,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
                 }
 
                 $interval = mb_substr($interval, mb_strlen($match[0]));
-                $instance->$unit += \intval($match[0]);
+                $instance->$unit += (int) ($match[0]);
 
                 continue;
             }
@@ -546,7 +546,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
                     "'$expected'",
                     $nextCharacter,
                     'Allowed substitutes for interval formats are '.implode(', ', array_keys(static::$formats))."\n".
-                    'See https://www.php.net/manual/en/function.date.php for their meaning'
+                    'See https://php.net/manual/en/function.date.php for their meaning'
                 );
             }
 
@@ -679,8 +679,8 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
         preg_match_all($pattern, $intervalDefinition, $parts, PREG_SET_ORDER);
 
         while ([$part, $value, $unit] = array_shift($parts)) {
-            $intValue = \intval($value);
-            $fraction = \floatval($value) - $intValue;
+            $intValue = (int) $value;
+            $fraction = (float) $value - $intValue;
 
             // Fix calculation precision
             switch (round($fraction, 6)) {
@@ -964,7 +964,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
      *
      * @return static
      *
-     * @link http://php.net/manual/en/dateinterval.createfromdatestring.php
+     * @link https://php.net/manual/en/dateinterval.createfromdatestring.php
      */
     #[ReturnTypeWillChange]
     public static function createFromDateString($time)
@@ -996,7 +996,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
      */
     public function get($name)
     {
-        if (substr($name, 0, 5) === 'total') {
+        if (str_starts_with($name, 'total')) {
             return $this->total(substr($name, 5));
         }
 
@@ -1360,7 +1360,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
         $minimumUnit = 's';
         extract($this->getForHumansInitialVariables($syntax, $short));
 
-        if (\is_null($syntax)) {
+        if ($syntax === null) {
             $syntax = CarbonInterface::DIFF_ABSOLUTE;
         }
 
@@ -1368,7 +1368,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
             $parts = INF;
         }
 
-        if (\is_null($options)) {
+        if ($options === null) {
             $options = static::getHumanDiffOptions();
         }
 
@@ -1860,7 +1860,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
             [$value, $unit] = [$unit, $value];
         }
 
-        return $this->add($unit, -\floatval($value));
+        return $this->add($unit, -(float) $value);
     }
 
     /**
@@ -2104,7 +2104,7 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
     public static function compareDateIntervals(DateInterval $first, DateInterval $second)
     {
         $current = Carbon::now();
-        $passed = $current->copy()->add($second);
+        $passed = $current->avoidMutation()->add($second);
         $current->add($first);
 
         if ($current < $passed) {
@@ -2242,12 +2242,12 @@ class CarbonInterval extends DateInterval implements CarbonConverterInterface
             'years' => $this->years,
             'months' => $this->months,
             'weeks' => (int) ($this->d / $daysPerWeek),
-            'dayz' => (int) ($this->d % $daysPerWeek),
+            'dayz' => $this->d % $daysPerWeek,
             'hours' => $this->hours,
             'minutes' => $this->minutes,
             'seconds' => $this->seconds,
             'milliseconds' => (int) ($this->microseconds / Carbon::MICROSECONDS_PER_MILLISECOND),
-            'microseconds' => (int) ($this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND),
+            'microseconds' => $this->microseconds % Carbon::MICROSECONDS_PER_MILLISECOND,
         ];
 
         if (isset($factors['dayz']) && $factors['dayz'][0] !== 'weeks') {
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonPeriod.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonPeriod.php
index bc918a93..70e6ba49 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonPeriod.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonPeriod.php
@@ -32,6 +32,7 @@ use InvalidArgumentException;
 use Iterator;
 use JsonSerializable;
 use ReflectionException;
+use ReturnTypeWillChange;
 use RuntimeException;
 
 /**
@@ -875,7 +876,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
      */
     public function setOptions($options)
     {
-        if (!\is_int($options) && !\is_null($options)) {
+        if (!\is_int($options) && $options !== null) {
             throw new InvalidPeriodParameterException('Invalid options.');
         }
 
@@ -962,7 +963,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
      */
     public function getStartDate(string $rounding = null)
     {
-        $date = $this->startDate->copy();
+        $date = $this->startDate->avoidMutation();
 
         return $rounding ? $date->round($this->getDateInterval(), $rounding) : $date;
     }
@@ -980,7 +981,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
             return null;
         }
 
-        $date = $this->endDate->copy();
+        $date = $this->endDate->avoidMutation();
 
         return $rounding ? $date->round($this->getDateInterval(), $rounding) : $date;
     }
@@ -1220,7 +1221,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
      */
     public function setRecurrences($recurrences)
     {
-        if (!is_numeric($recurrences) && !\is_null($recurrences) || $recurrences < 0) {
+        if (!is_numeric($recurrences) && $recurrences !== null || $recurrences < 0) {
             throw new InvalidPeriodParameterException('Invalid number of recurrences.');
         }
 
@@ -1276,7 +1277,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
      */
     public function setEndDate($date, $inclusive = null)
     {
-        if (!\is_null($date) && !$date = ([$this->dateClass, 'make'])($date)) {
+        if ($date !== null && !$date = ([$this->dateClass, 'make'])($date)) {
             throw new InvalidPeriodDateException('Invalid end date.');
         }
 
@@ -1523,7 +1524,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
     {
         $state = [
             $this->key,
-            $this->current ? $this->current->copy() : null,
+            $this->current ? $this->current->avoidMutation() : null,
             $this->validationResult,
         ];
 
@@ -1722,7 +1723,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
         $date = $this->getEndFromRecurrences() ?? $this->iterateUntilEnd();
 
         if ($date && $rounding) {
-            $date = $date->copy()->round($this->getDateInterval(), $rounding);
+            $date = $date->avoidMutation()->round($this->getDateInterval(), $rounding);
         }
 
         return $date;
@@ -1743,13 +1744,13 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
         if ($this->recurrences === INF) {
             $start = $this->getStartDate();
 
-            return $start < $start->copy()->add($this->getDateInterval())
+            return $start < $start->avoidMutation()->add($this->getDateInterval())
                 ? CarbonImmutable::endOfTime()
                 : CarbonImmutable::startOfTime();
         }
 
         if ($this->filters === [[static::RECURRENCES_FILTER, null]]) {
-            return $this->getStartDate()->copy()->add(
+            return $this->getStartDate()->avoidMutation()->add(
                 $this->getDateInterval()->times(
                     $this->recurrences - ($this->isStartExcluded() ? 0 : 1)
                 )
@@ -1795,13 +1796,8 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
             $range = static::create($range);
         }
 
-        $thisDates = [$this->getStartDate(), $this->calculateEnd()];
-        sort($thisDates);
-        [$start, $end] = $thisDates;
-
-        $rangeDates = [$range->getStartDate(), $range->calculateEnd()];
-        sort($rangeDates);
-        [$rangeStart, $rangeEnd] = $rangeDates;
+        [$start, $end] = $this->orderCouple($this->getStartDate(), $this->calculateEnd());
+        [$rangeStart, $rangeEnd] = $this->orderCouple($range->getStartDate(), $range->calculateEnd());
 
         return $end > $rangeStart && $rangeEnd > $start;
     }
@@ -2168,6 +2164,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
      *
      * @return CarbonInterface[]
      */
+    #[ReturnTypeWillChange]
     public function jsonSerialize()
     {
         return $this->toArray();
@@ -2283,7 +2280,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
      */
     protected function isCarbonPredicateMethod($callable)
     {
-        return \is_string($callable) && substr($callable, 0, 2) === 'is' &&
+        return \is_string($callable) && str_starts_with($callable, 'is') &&
             (method_exists($this->dateClass, $callable) || ([$this->dateClass, 'hasMacro'])($callable));
     }
 
@@ -2384,7 +2381,7 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
         foreach ($this->filters as $tuple) {
             $result = \call_user_func(
                 $tuple[0],
-                $current->copy(),
+                $current->avoidMutation(),
                 $this->key,
                 $this
             );
@@ -2493,4 +2490,9 @@ class CarbonPeriod implements Iterator, Countable, JsonSerializable
             ? static::instance($period)
             : static::create($period, ...$arguments);
     }
+
+    private function orderCouple($first, $second): array
+    {
+        return $first > $second ? [$second, $first] : [$first, $second];
+    }
 }
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonTimeZone.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonTimeZone.php
index dc4cbe07..2bd36c43 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonTimeZone.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/CarbonTimeZone.php
@@ -33,7 +33,7 @@ class CarbonTimeZone extends DateTimeZone
 
     protected static function getDateTimeZoneNameFromMixed($timezone)
     {
-        if (\is_null($timezone)) {
+        if ($timezone === null) {
             return date_default_timezone_get();
         }
 
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonTypeConverter.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonTypeConverter.php
index fb59410e..fa0d5b00 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonTypeConverter.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Doctrine/CarbonTypeConverter.php
@@ -37,7 +37,7 @@ trait CarbonTypeConverter
             return $type;
         }
 
-        if (strpos($type, '(') !== false) {
+        if (str_contains($type, '(')) {
             return preg_replace('/\(\d+\)/', "($precision)", $type);
         }
 
@@ -95,7 +95,7 @@ trait CarbonTypeConverter
             return $value;
         }
 
-        if ($value instanceof DateTimeInterface || $value instanceof CarbonInterface) {
+        if ($value instanceof DateTimeInterface) {
             return $value->format('Y-m-d H:i:s.u');
         }
 
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Factory.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Factory.php
index 8dbd488a..e1d747f2 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Factory.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Factory.php
@@ -215,7 +215,7 @@ use ReflectionMethod;
  *                                                                                                                                                                                                           You should rather use the ->settings() method.
  *                                                                                                                                                                                                           Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
  *                                                                                                                                                                                                           are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @method Carbon                                             withTestNow($testNow = null, $callback = null)                                                                                     Temporarily sets a static date to be used within the callback.
+ * @method mixed                                              withTestNow($testNow = null, $callback = null)                                                                                     Temporarily sets a static date to be used within the callback.
  *                                                                                                                                                                                               Using setTestNow to set the date, executing the callback, then
  *                                                                                                                                                                                               clearing the test instance.
  *                                                                                                                                                                                               /!\ Use this method for unit tests only.
@@ -229,7 +229,7 @@ class Factory
 
     protected $settings = [];
 
-    public function __construct(array $settings = [], string $className = null)
+    public function __construct(array $settings = [], ?string $className = null)
     {
         if ($className) {
             $this->className = $className;
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/FactoryImmutable.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/FactoryImmutable.php
index 0cec0fdf..3aa286c0 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/FactoryImmutable.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/FactoryImmutable.php
@@ -214,7 +214,7 @@ use Closure;
  *                                                                                                                                                                                                           You should rather use the ->settings() method.
  *                                                                                                                                                                                                           Or you can use method variants: addYearsWithOverflow/addYearsNoOverflow, same variants
  *                                                                                                                                                                                                           are available for quarters, years, decade, centuries, millennia (singular and plural forms).
- * @method CarbonImmutable                                    withTestNow($testNow = null, $callback = null)                                                                                     Temporarily sets a static date to be used within the callback.
+ * @method mixed                                              withTestNow($testNow = null, $callback = null)                                                                                     Temporarily sets a static date to be used within the callback.
  *                                                                                                                                                                                               Using setTestNow to set the date, executing the callback, then
  *                                                                                                                                                                                               clearing the test instance.
  *                                                                                                                                                                                               /!\ Use this method for unit tests only.
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/be.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/be.php
index 6db1a922..ce8dbe83 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/be.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/be.php
@@ -11,7 +11,7 @@
 // @codeCoverageIgnoreStart
 if (class_exists('Symfony\\Component\\Translation\\PluralizationRules')) {
     \Symfony\Component\Translation\PluralizationRules::set(function ($number) {
-        return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
+        return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
     }, 'be');
 }
 // @codeCoverageIgnoreEnd
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bn_BD.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bn_BD.php
index 46d52141..b5b28dd1 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bn_BD.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/bn_BD.php
@@ -11,7 +11,7 @@
 
 /*
  * Authors:
- * - Ankur Group, http://www.ankurbangla.org, http://www.bengalinux.org Taneem Ahmed, Jamil Ahmed [email protected], [email protected]
+ * - Ankur Group, Taneem Ahmed, Jamil Ahmed
  */
 return array_replace_recursive(require __DIR__.'/bn.php', [
     'formats' => [
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gl.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gl.php
index 6a06b026..58c1db15 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gl.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/gl.php
@@ -41,7 +41,7 @@ return [
     's' => ':count seg.',
     'ago' => 'hai :time',
     'from_now' => function ($time) {
-        if (substr($time, 0, 2) === 'un') {
+        if (str_starts_with($time, 'un')) {
             return "n$time";
         }
 
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ka.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ka.php
index 3cdbe2d2..5ddb957d 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ka.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/ka.php
@@ -169,8 +169,8 @@ return [
 
         return $number.'-ე';
     },
-    'months' => ['იანვარს', 'თებერვალს', 'მარტს', 'აპრილის', 'მაისს', 'ივნისს', 'ივლისს', 'აგვისტს', 'სექტემბერს', 'ოქტომბერს', 'ნოემბერს', 'დეკემბერს'],
-    'months_standalone' => ['იანვარი', 'თებერვალი', 'მარტი', 'აპრილი', 'მაისი', 'ივნისი', 'ივლისი', 'აგვისტო', 'სექტემბერი', 'ოქტომბერი', 'ნოემბერი', 'დეკემბერი'],
+    'months' => ['იანვარი', 'თებერვალი', 'მარტი', 'აპრილი', 'მაისი', 'ივნისი', 'ივლისი', 'აგვისტო', 'სექტემბერი', 'ოქტომბერი', 'ნოემბერი', 'დეკემბერი'],
+    'months_standalone' => ['იანვარს', 'თებერვალს', 'მარტს', 'აპრილს', 'მაისს', 'ივნისს', 'ივლისს', 'აგვისტოს', 'სექტემბერს', 'ოქტომბერს', 'ნოემბერს', 'დეკემბერს'],
     'months_short' => ['იან', 'თებ', 'მარ', 'აპრ', 'მაი', 'ივნ', 'ივლ', 'აგვ', 'სექ', 'ოქტ', 'ნოე', 'დეკ'],
     'months_regexp' => '/(D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|L{2,4}|l{2,4})/',
     'weekdays' => ['კვირას', 'ორშაბათს', 'სამშაბათს', 'ოთხშაბათს', 'ხუთშაბათს', 'პარასკევს', 'შაბათს'],
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl.php
index 0146af92..fc8b5d9a 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/nl.php
@@ -69,7 +69,7 @@ return [
     'diff_after_tomorrow' => 'overmorgen',
     'diff_before_yesterday' => 'eergisteren',
     'period_recurrences' => ':count keer',
-    'period_interval' => function ($interval) {
+    'period_interval' => function (string $interval = '') {
         /** @var string $output */
         $output = preg_replace('/^(een|één|1)\s+/', '', $interval);
 
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/oc.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/oc.php
index 7cc6ec17..94c3e04c 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/oc.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/oc.php
@@ -82,7 +82,7 @@ return [
     'weekdays' => ['dimenge', 'diluns', 'dimars', 'dimècres', 'dijòus', 'divendres', 'dissabte'],
     'weekdays_short' => ['dg', 'dl', 'dm', 'dc', 'dj', 'dv', 'ds'],
     'weekdays_min' => ['dg', 'dl', 'dm', 'dc', 'dj', 'dv', 'ds'],
-    'ordinal' => function ($number, $period) {
+    'ordinal' => function ($number, string $period = '') {
         $ordinal = [1 => 'èr', 2 => 'nd'][(int) $number] ?? 'en';
 
         // feminine for year, week, hour, minute, second
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pl.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pl.php
index 9eed5eff..ca10fe4a 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pl.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/pl.php
@@ -29,7 +29,7 @@
 return [
     'year' => ':count rok|:count lata|:count lat',
     'a_year' => 'rok|:count lata|:count lat',
-    'y' => ':count r|:count l',
+    'y' => ':count r|:count l|:count l',
     'month' => ':count miesiąc|:count miesiące|:count miesięcy',
     'a_month' => 'miesiąc|:count miesiące|:count miesięcy',
     'm' => ':count mies.',
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sh.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sh.php
index aaf82026..a953df42 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sh.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/sh.php
@@ -11,7 +11,7 @@
 // @codeCoverageIgnoreStart
 if (class_exists('Symfony\\Component\\Translation\\PluralizationRules')) {
     \Symfony\Component\Translation\PluralizationRules::set(function ($number) {
-        return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
+        return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2);
     }, 'sh');
 }
 // @codeCoverageIgnoreEnd
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shn_MM.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shn_MM.php
index c3f792c1..f399acf0 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shn_MM.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Lang/shn_MM.php
@@ -11,7 +11,7 @@
 
 /*
  * Authors:
- * - ubuntu Myanmar LoCo Team http://www.ubuntu-mm.net Bone Pyae Sone [email protected]
+ * - ubuntu Myanmar LoCo Team https://ubuntu-mm.net Bone Pyae Sone [email protected]
  */
 return array_replace_recursive(require __DIR__.'/en.php', [
     'formats' => [
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Language.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Language.php
index 2700ee7b..37902854 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Language.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Language.php
@@ -11,6 +11,7 @@
 namespace Carbon;
 
 use JsonSerializable;
+use ReturnTypeWillChange;
 
 class Language implements JsonSerializable
 {
@@ -332,6 +333,7 @@ class Language implements JsonSerializable
      *
      * @return string
      */
+    #[ReturnTypeWillChange]
     public function jsonSerialize()
     {
         return $this->getIsoDescription();
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Comparison.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Comparison.php
index 18dc5e45..ee00666c 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Comparison.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Comparison.php
@@ -622,7 +622,7 @@ trait Comparison
 
         if (!isset($units[$unit])) {
             if (isset($this->$unit)) {
-                return $this->$unit === $this->resolveCarbon($date)->$unit;
+                return $this->resolveCarbon($date)->$unit === $this->$unit;
             }
 
             if ($this->localStrictModeEnabled ?? static::isStrictModeEnabled()) {
@@ -949,7 +949,7 @@ trait Comparison
         $tester = trim($tester);
 
         if (preg_match('/^\d+$/', $tester)) {
-            return $this->year === \intval($tester);
+            return $this->year === (int) $tester;
         }
 
         if (preg_match('/^\d{3,}-\d{1,2}$/', $tester)) {
@@ -964,9 +964,9 @@ trait Comparison
 
         /* @var CarbonInterface $max */
         $median = static::parse('5555-06-15 12:30:30.555555')->modify($modifier);
-        $current = $this->copy();
+        $current = $this->avoidMutation();
         /* @var CarbonInterface $other */
-        $other = $this->copy()->modify($modifier);
+        $other = $this->avoidMutation()->modify($modifier);
 
         if ($current->eq($other)) {
             return true;
@@ -1001,7 +1001,7 @@ trait Comparison
         ];
 
         foreach ($units as $unit => [$minimum, $startUnit]) {
-            if ($median->$unit === $minimum) {
+            if ($minimum === $median->$unit) {
                 $current = $current->startOf($startUnit);
 
                 break;
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Converter.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Converter.php
index 38ffd193..7ba62256 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Converter.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Converter.php
@@ -38,7 +38,7 @@ trait Converter
      *
      * @var string|Closure|null
      */
-    protected static $toStringFormat = null;
+    protected static $toStringFormat;
 
     /**
      * Reset the format used to the default when type juggling a Carbon instance to a string
@@ -324,7 +324,9 @@ trait Converter
      */
     public function toIso8601ZuluString($unitPrecision = 'second')
     {
-        return $this->copy()->utc()->rawFormat('Y-m-d\T'.static::getTimeFormatByPrecision($unitPrecision).'\Z');
+        return $this->avoidMutation()
+            ->utc()
+            ->rawFormat('Y-m-d\T'.static::getTimeFormatByPrecision($unitPrecision).'\Z');
     }
 
     /**
@@ -452,7 +454,7 @@ trait Converter
      */
     public function toRfc7231String()
     {
-        return $this->copy()
+        return $this->avoidMutation()
             ->setTimezone('GMT')
             ->rawFormat(\defined('static::RFC7231_FORMAT') ? static::RFC7231_FORMAT : CarbonInterface::RFC7231_FORMAT);
     }
@@ -512,7 +514,7 @@ trait Converter
      */
     public function toString()
     {
-        return $this->copy()->locale('en')->isoFormat('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
+        return $this->avoidMutation()->locale('en')->isoFormat('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
     }
 
     /**
@@ -537,7 +539,7 @@ trait Converter
 
         $yearFormat = $this->year < 0 || $this->year > 9999 ? 'YYYYYY' : 'YYYY';
         $tzFormat = $keepOffset ? 'Z' : '[Z]';
-        $date = $keepOffset ? $this : $this->copy()->utc();
+        $date = $keepOffset ? $this : $this->avoidMutation()->utc();
 
         return $date->isoFormat("$yearFormat-MM-DD[T]HH:mm:ss.SSSSSS$tzFormat");
     }
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Creator.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Creator.php
index 25ab6ec9..fa7cfc7b 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Creator.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Creator.php
@@ -77,7 +77,7 @@ trait Creator
         }
 
         // Work-around for PHP bug https://bugs.php.net/bug.php?id=67127
-        if (strpos((string) .1, '.') === false) {
+        if (!str_contains((string) .1, '.')) {
             $locale = setlocale(LC_NUMERIC, '0');
             setlocale(LC_NUMERIC, 'C');
         }
@@ -592,7 +592,7 @@ trait Creator
         // @codeCoverageIgnoreEnd
 
         if ($originalTz === null) {
-            return parent::createFromFormat($format, "$time");
+            return parent::createFromFormat($format, (string) $time);
         }
 
         $tz = \is_int($originalTz)
@@ -605,7 +605,7 @@ trait Creator
             return false;
         }
 
-        return parent::createFromFormat($format, "$time", $tz);
+        return parent::createFromFormat($format, (string) $time, $tz);
     }
 
     /**
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Date.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Date.php
index a4b0fce2..07ac0dde 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Date.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Date.php
@@ -27,6 +27,7 @@ use Closure;
 use DateInterval;
 use DatePeriod;
 use DateTime;
+use DateTimeImmutable;
 use DateTimeInterface;
 use DateTimeZone;
 use InvalidArgumentException;
@@ -630,7 +631,7 @@ trait Date
      *
      * @return CarbonTimeZone
      *
-     * @link http://php.net/manual/en/datetime.gettimezone.php
+     * @link https://php.net/manual/en/datetime.gettimezone.php
      */
     #[ReturnTypeWillChange]
     public function getTimezone()
@@ -683,6 +684,23 @@ trait Date
         return clone $this;
     }
 
+    /**
+     * Clone the current instance if it's mutable.
+     *
+     * This method is convenient to ensure you don't mutate the initial object
+     * but avoid to make a useless copy of it if it's already immutable.
+     *
+     * @return static
+     */
+    public function avoidMutation(): self
+    {
+        if ($this instanceof DateTimeImmutable) {
+            return $this;
+        }
+
+        return clone $this;
+    }
+
     /**
      * Returns a present instance in the same timezone.
      *
@@ -774,7 +792,7 @@ trait Date
     public function carbonize($date = null)
     {
         if ($date instanceof DateInterval) {
-            return $this->copy()->add($date);
+            return $this->avoidMutation()->add($date);
         }
 
         if ($date instanceof DatePeriod || $date instanceof CarbonPeriod) {
@@ -872,7 +890,7 @@ trait Date
         switch (true) {
             case isset($formats[$name]):
                 $format = $formats[$name];
-                $method = substr($format, 0, 1) === '%' ? 'formatLocalized' : 'rawFormat';
+                $method = str_starts_with($format, '%') ? 'formatLocalized' : 'rawFormat';
                 $value = $this->$method($format);
 
                 return is_numeric($value) ? (int) $value : $value;
@@ -927,11 +945,11 @@ trait Date
 
             // @property-read int 51 through 53
             case $name === 'weeksInYear':
-                return (int) $this->weeksInYear();
+                return $this->weeksInYear();
 
             // @property-read int 51 through 53
             case $name === 'isoWeeksInYear':
-                return (int) $this->isoWeeksInYear();
+                return $this->isoWeeksInYear();
 
             // @property-read int 1 through 5
             case $name === 'weekOfMonth':
@@ -939,7 +957,7 @@ trait Date
 
             // @property-read int 1 through 5
             case $name === 'weekNumberInMonth':
-                return (int) ceil(($this->day + $this->copy()->startOfMonth()->dayOfWeekIso - 1) / static::DAYS_PER_WEEK);
+                return (int) ceil(($this->day + $this->avoidMutation()->startOfMonth()->dayOfWeekIso - 1) / static::DAYS_PER_WEEK);
 
             // @property-read int 0 through 6
             case $name === 'firstWeekDay':
@@ -951,7 +969,7 @@ trait Date
 
             // @property int 1 through 366
             case $name === 'dayOfYear':
-                return 1 + \intval($this->rawFormat('z'));
+                return 1 + (int) ($this->rawFormat('z'));
 
             // @property-read int 365 or 366
             case $name === 'daysInYear':
@@ -1013,7 +1031,7 @@ trait Date
 
             // @property-read bool checks if the timezone is local, true if local, false otherwise
             case $name === 'local':
-                return $this->getOffset() === $this->copy()->setTimezone(date_default_timezone_get())->getOffset();
+                return $this->getOffset() === $this->avoidMutation()->setTimezone(date_default_timezone_get())->getOffset();
 
             // @property-read bool checks if the timezone is UTC, true if UTC, false otherwise
             case $name === 'utc':
@@ -1114,7 +1132,7 @@ trait Date
             case 'microseconds':
             case 'microsecond':
             case 'micro':
-                if (substr($name, 0, 5) === 'milli') {
+                if (str_starts_with($name, 'milli')) {
                     $value *= 1000;
                 }
 
@@ -1309,7 +1327,7 @@ trait Date
     {
         $dayOfYear = $this->dayOfYear;
 
-        return \is_null($value) ? $dayOfYear : $this->addDays($value - $dayOfYear);
+        return $value === null ? $dayOfYear : $this->addDays($value - $dayOfYear);
     }
 
     /**
@@ -1321,9 +1339,9 @@ trait Date
      */
     public function weekday($value = null)
     {
-        $dayOfWeek = ($this->dayOfWeek + 7 - \intval($this->getTranslationMessage('first_day_of_week') ?? 0)) % 7;
+        $dayOfWeek = ($this->dayOfWeek + 7 - (int) ($this->getTranslationMessage('first_day_of_week') ?? 0)) % 7;
 
-        return \is_null($value) ? $dayOfWeek : $this->addDays($value - $dayOfWeek);
+        return $value === null ? $dayOfWeek : $this->addDays($value - $dayOfWeek);
     }
 
     /**
@@ -1337,7 +1355,7 @@ trait Date
     {
         $dayOfWeekIso = $this->dayOfWeekIso;
 
-        return \is_null($value) ? $dayOfWeekIso : $this->addDays($value - $dayOfWeekIso);
+        return $value === null ? $dayOfWeekIso : $this->addDays($value - $dayOfWeekIso);
     }
 
     /**
@@ -1352,11 +1370,11 @@ trait Date
     public function setUnitNoOverflow($valueUnit, $value, $overflowUnit)
     {
         try {
-            $original = $this->copy();
+            $original = $this->avoidMutation();
             /** @var static $date */
             $date = $this->$valueUnit($value);
-            $end = $original->copy()->endOf($overflowUnit);
-            $start = $original->copy()->startOf($overflowUnit);
+            $end = $original->avoidMutation()->endOf($overflowUnit);
+            $start = $original->avoidMutation()->startOf($overflowUnit);
             if ($date < $start) {
                 $date = $date->setDateTimeFrom($start);
             } elseif ($date > $end) {
@@ -1509,7 +1527,7 @@ trait Date
      */
     public function setTimeFromTimeString($time)
     {
-        if (strpos($time, ':') === false) {
+        if (!str_contains($time, ':')) {
             $time .= ':0';
         }
 
@@ -1791,7 +1809,7 @@ trait Date
 
     /**
      * Format the instance with the current locale.  You can set the current
-     * locale using setlocale() http://php.net/setlocale.
+     * locale using setlocale() https://php.net/setlocale.
      *
      * @param string $format
      *
@@ -1900,7 +1918,7 @@ trait Date
                 's' => 'second',
                 'ss' => ['getPaddedUnit', ['second']],
                 'S' => function (CarbonInterface $date) {
-                    return \strval((string) floor($date->micro / 100000));
+                    return (string) floor($date->micro / 100000);
                 },
                 'SS' => function (CarbonInterface $date) {
                     return str_pad((string) floor($date->micro / 10000), 2, '0', STR_PAD_LEFT);
@@ -1999,15 +2017,15 @@ trait Date
      *
      * @return string
      */
-    public function ordinal(string $key, string $period = null): string
+    public function ordinal(string $key, ?string $period = null): string
     {
         $number = $this->$key;
         $result = $this->translate('ordinal', [
             ':number' => $number,
-            ':period' => $period,
+            ':period' => (string) $period,
         ]);
 
-        return \strval($result === 'ordinal' ? $number : $result);
+        return (string) ($result === 'ordinal' ? $number : $result);
     }
 
     /**
@@ -2070,7 +2088,7 @@ trait Date
      *
      * @return string
      */
-    public function isoFormat(string $format, string $originalFormat = null): string
+    public function isoFormat(string $format, ?string $originalFormat = null): string
     {
         $result = '';
         $length = mb_strlen($format);
@@ -2149,7 +2167,7 @@ trait Date
                 }
 
                 $format = mb_substr($format, 0, $i).$sequence.mb_substr($format, $i + mb_strlen($code));
-                $i += mb_strlen("$sequence") - 1;
+                $i += mb_strlen((string) $sequence) - 1;
                 $length = mb_strlen($format);
                 $char = $sequence;
             }
@@ -2179,7 +2197,7 @@ trait Date
                 'S' => function ($date) {
                     $day = $date->rawFormat('j');
 
-                    return str_replace("$day", '', $date->isoFormat('Do'));
+                    return str_replace((string) $day, '', $date->isoFormat('Do'));
                 },
                 'w' => true,
                 'z' => true,
@@ -2219,7 +2237,7 @@ trait Date
     }
 
     /**
-     * Format as ->format() do (using date replacements patterns from http://php.net/manual/fr/function.date.php)
+     * Format as ->format() do (using date replacements patterns from https://php.net/manual/en/function.date.php)
      * but translate words whenever possible (months, day names, etc.) using the current locale.
      *
      * @param string $format
@@ -2519,7 +2537,7 @@ trait Date
 
         $unit = rtrim($method, 's');
 
-        if (substr($unit, 0, 2) === 'is') {
+        if (str_starts_with($unit, 'is')) {
             $word = substr($unit, 2);
 
             if (\in_array($word, static::$days)) {
@@ -2557,7 +2575,7 @@ trait Date
         if ($action === 'add' || $action === 'sub') {
             $unit = substr($unit, 3);
 
-            if (substr($unit, 0, 4) === 'Real') {
+            if (str_starts_with($unit, 'Real')) {
                 $unit = static::singularUnit(substr($unit, 4));
 
                 return $this->{"${action}RealUnit"}($unit, ...$parameters);
@@ -2599,7 +2617,7 @@ trait Date
             }
         }
 
-        if (substr($unit, 0, 9) === 'isCurrent') {
+        if (str_starts_with($unit, 'isCurrent')) {
             try {
                 return $this->isCurrentUnit(strtolower(substr($unit, 9)));
             } catch (BadComparisonUnitException | BadMethodCallException $exception) {
@@ -2607,7 +2625,7 @@ trait Date
             }
         }
 
-        if (substr($method, -5) === 'Until') {
+        if (str_ends_with($method, 'Until')) {
             try {
                 $unit = static::singularUnit(substr($method, 0, -5));
 
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Difference.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Difference.php
index 335ad2be..b1cdd6e3 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Difference.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Difference.php
@@ -121,7 +121,17 @@ trait Difference
     #[ReturnTypeWillChange]
     public function diff($date = null, $absolute = false)
     {
-        return parent::diff($this->resolveCarbon($date), (bool) $absolute);
+        $other = $this->resolveCarbon($date);
+
+        // Can be removed if https://github.com/derickr/timelib/pull/110
+        // is merged
+        // @codeCoverageIgnoreStart
+        if (version_compare(PHP_VERSION, '8.1.0-dev', '>=') && $other->tz !== $this->tz) {
+            $other = $other->avoidMutation()->tz($this->tz);
+        }
+        // @codeCoverageIgnoreEnd
+
+        return parent::diff($other, (bool) $absolute);
     }
 
     /**
@@ -540,14 +550,14 @@ trait Difference
         }
         $monthsDiff = $start->diffInMonths($end);
         /** @var Carbon|CarbonImmutable $floorEnd */
-        $floorEnd = $start->copy()->addMonths($monthsDiff);
+        $floorEnd = $start->avoidMutation()->addMonths($monthsDiff);
 
         if ($floorEnd >= $end) {
             return $sign * $monthsDiff;
         }
 
         /** @var Carbon|CarbonImmutable $startOfMonthAfterFloorEnd */
-        $startOfMonthAfterFloorEnd = $floorEnd->copy()->addMonth()->startOfMonth();
+        $startOfMonthAfterFloorEnd = $floorEnd->avoidMutation()->addMonth()->startOfMonth();
 
         if ($startOfMonthAfterFloorEnd > $end) {
             return $sign * ($monthsDiff + $floorEnd->floatDiffInDays($end) / $floorEnd->daysInMonth);
@@ -575,14 +585,14 @@ trait Difference
         }
         $yearsDiff = $start->diffInYears($end);
         /** @var Carbon|CarbonImmutable $floorEnd */
-        $floorEnd = $start->copy()->addYears($yearsDiff);
+        $floorEnd = $start->avoidMutation()->addYears($yearsDiff);
 
         if ($floorEnd >= $end) {
             return $sign * $yearsDiff;
         }
 
         /** @var Carbon|CarbonImmutable $startOfYearAfterFloorEnd */
-        $startOfYearAfterFloorEnd = $floorEnd->copy()->addYear()->startOfYear();
+        $startOfYearAfterFloorEnd = $floorEnd->avoidMutation()->addYear()->startOfYear();
 
         if ($startOfYearAfterFloorEnd > $end) {
             return $sign * ($yearsDiff + $floorEnd->floatDiffInDays($end) / $floorEnd->daysInYear);
@@ -641,7 +651,7 @@ trait Difference
     public function floatDiffInRealDays($date = null, $absolute = true)
     {
         $date = $this->resolveUTC($date);
-        $utc = $this->copy()->utc();
+        $utc = $this->avoidMutation()->utc();
         $hoursDiff = $utc->floatDiffInRealHours($date, $absolute);
 
         return ($hoursDiff < 0 ? -1 : 1) * $utc->diffInDays($date) + fmod($hoursDiff, static::HOURS_PER_DAY) / static::HOURS_PER_DAY;
@@ -679,14 +689,14 @@ trait Difference
         }
         $monthsDiff = $start->diffInMonths($end);
         /** @var Carbon|CarbonImmutable $floorEnd */
-        $floorEnd = $start->copy()->addMonths($monthsDiff);
+        $floorEnd = $start->avoidMutation()->addMonths($monthsDiff);
 
         if ($floorEnd >= $end) {
             return $sign * $monthsDiff;
         }
 
         /** @var Carbon|CarbonImmutable $startOfMonthAfterFloorEnd */
-        $startOfMonthAfterFloorEnd = $floorEnd->copy()->addMonth()->startOfMonth();
+        $startOfMonthAfterFloorEnd = $floorEnd->avoidMutation()->addMonth()->startOfMonth();
 
         if ($startOfMonthAfterFloorEnd > $end) {
             return $sign * ($monthsDiff + $floorEnd->floatDiffInRealDays($end) / $floorEnd->daysInMonth);
@@ -714,14 +724,14 @@ trait Difference
         }
         $yearsDiff = $start->diffInYears($end);
         /** @var Carbon|CarbonImmutable $floorEnd */
-        $floorEnd = $start->copy()->addYears($yearsDiff);
+        $floorEnd = $start->avoidMutation()->addYears($yearsDiff);
 
         if ($floorEnd >= $end) {
             return $sign * $yearsDiff;
         }
 
         /** @var Carbon|CarbonImmutable $startOfYearAfterFloorEnd */
-        $startOfYearAfterFloorEnd = $floorEnd->copy()->addYear()->startOfYear();
+        $startOfYearAfterFloorEnd = $floorEnd->avoidMutation()->addYear()->startOfYear();
 
         if ($startOfYearAfterFloorEnd > $end) {
             return $sign * ($yearsDiff + $floorEnd->floatDiffInRealDays($end) / $floorEnd->daysInYear);
@@ -737,7 +747,7 @@ trait Difference
      */
     public function secondsSinceMidnight()
     {
-        return $this->diffInSeconds($this->copy()->startOfDay());
+        return $this->diffInSeconds($this->avoidMutation()->startOfDay());
     }
 
     /**
@@ -747,7 +757,7 @@ trait Difference
      */
     public function secondsUntilEndOfDay()
     {
-        return $this->diffInSeconds($this->copy()->endOfDay());
+        return $this->diffInSeconds($this->avoidMutation()->endOfDay());
     }
 
     /**
@@ -1106,9 +1116,9 @@ trait Difference
     public function calendar($referenceTime = null, array $formats = [])
     {
         /** @var CarbonInterface $current */
-        $current = $this->copy()->startOfDay();
+        $current = $this->avoidMutation()->startOfDay();
         /** @var CarbonInterface $other */
-        $other = $this->resolveCarbon($referenceTime)->copy()->setTimezone($this->getTimezone())->startOfDay();
+        $other = $this->resolveCarbon($referenceTime)->avoidMutation()->setTimezone($this->getTimezone())->startOfDay();
         $diff = $other->diffInDays($current, false);
         $format = $diff < -6 ? 'sameElse' : (
             $diff < -1 ? 'lastWeek' : (
@@ -1126,6 +1136,6 @@ trait Difference
             $format = $format($current, $other) ?? '';
         }
 
-        return $this->isoFormat(\strval($format));
+        return $this->isoFormat((string) $format);
     }
 }
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/IntervalStep.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/IntervalStep.php
index 764bd1ea..4882eef6 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/IntervalStep.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/IntervalStep.php
@@ -64,7 +64,7 @@ trait IntervalStep
         $carbonDate = $dateTime instanceof CarbonInterface ? $dateTime : $this->resolveCarbon($dateTime);
 
         if ($this->step) {
-            return $carbonDate->setDateTimeFrom(($this->step)($carbonDate->copy(), $negated));
+            return $carbonDate->setDateTimeFrom(($this->step)($carbonDate->avoidMutation(), $negated));
         }
 
         if ($negated) {
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Localization.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Localization.php
index 7bbedf99..9162dc94 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Localization.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Localization.php
@@ -168,7 +168,7 @@ trait Localization
      *
      * @return string
      */
-    public static function getTranslationMessageWith($translator, string $key, string $locale = null, string $default = null)
+    public static function getTranslationMessageWith($translator, string $key, ?string $locale = null, ?string $default = null)
     {
         if (!($translator instanceof TranslatorBagInterface && $translator instanceof TranslatorInterface)) {
             throw new InvalidTypeException(
@@ -196,7 +196,7 @@ trait Localization
      *
      * @return string
      */
-    public function getTranslationMessage(string $key, string $locale = null, string $default = null, $translator = null)
+    public function getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null)
     {
         return static::getTranslationMessageWith($translator ?: $this->getLocalTranslator(), $key, $locale, $default);
     }
@@ -239,12 +239,12 @@ trait Localization
      *
      * @param string                                             $key
      * @param array                                              $parameters
-     * @param null                                               $number
+     * @param string|int|float|null                              $number
      * @param \Symfony\Component\Translation\TranslatorInterface $translator
      *
      * @return string
      */
-    public function translate(string $key, array $parameters = [], $number = null, TranslatorInterface $translator = null, bool $altNumbers = false): string
+    public function translate(string $key, array $parameters = [], $number = null, ?TranslatorInterface $translator = null, bool $altNumbers = false): string
     {
         $translation = static::translateWith($translator ?: $this->getLocalTranslator(), $key, $parameters, $number);
 
@@ -302,7 +302,7 @@ trait Localization
             return $result;
         }
 
-        return "$number";
+        return (string) $number;
     }
 
     /**
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Modifiers.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Modifiers.php
index 0b0ccc95..2fd64264 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Modifiers.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Modifiers.php
@@ -224,11 +224,11 @@ trait Modifiers
      */
     public function nthOfMonth($nth, $dayOfWeek)
     {
-        $date = $this->copy()->firstOfMonth();
+        $date = $this->avoidMutation()->firstOfMonth();
         $check = $date->rawFormat('Y-m');
         $date = $date->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
 
-        return $date->rawFormat('Y-m') === $check ? $this->modify("$date") : false;
+        return $date->rawFormat('Y-m') === $check ? $this->modify((string) $date) : false;
     }
 
     /**
@@ -274,12 +274,12 @@ trait Modifiers
      */
     public function nthOfQuarter($nth, $dayOfWeek)
     {
-        $date = $this->copy()->day(1)->month($this->quarter * static::MONTHS_PER_QUARTER);
+        $date = $this->avoidMutation()->day(1)->month($this->quarter * static::MONTHS_PER_QUARTER);
         $lastMonth = $date->month;
         $year = $date->year;
         $date = $date->firstOfQuarter()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
 
-        return ($lastMonth < $date->month || $year !== $date->year) ? false : $this->modify("$date");
+        return ($lastMonth < $date->month || $year !== $date->year) ? false : $this->modify((string) $date);
     }
 
     /**
@@ -325,9 +325,9 @@ trait Modifiers
      */
     public function nthOfYear($nth, $dayOfWeek)
     {
-        $date = $this->copy()->firstOfYear()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
+        $date = $this->avoidMutation()->firstOfYear()->modify('+'.$nth.' '.static::$days[$dayOfWeek]);
 
-        return $this->year === $date->year ? $this->modify("$date") : false;
+        return $this->year === $date->year ? $this->modify((string) $date) : false;
     }
 
     /**
@@ -454,7 +454,7 @@ trait Modifiers
     {
         return $this->modify(preg_replace_callback('/^(next|previous|last)\s+(\d{1,2}(h|am|pm|:\d{1,2}(:\d{1,2})?))$/i', function ($match) {
             $match[2] = str_replace('h', ':00', $match[2]);
-            $test = $this->copy()->modify($match[2]);
+            $test = $this->avoidMutation()->modify($match[2]);
             $method = $match[1] === 'next' ? 'lt' : 'gt';
             $match[1] = $test->$method($this) ? $match[1].' day' : 'today';
 
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/ObjectInitialisation.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/ObjectInitialisation.php
index fadfeaa8..252df3a5 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/ObjectInitialisation.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/ObjectInitialisation.php
@@ -17,5 +17,5 @@ trait ObjectInitialisation
      *
      * @var string
      */
-    protected $constructedObjectId = null;
+    protected $constructedObjectId;
 }
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Options.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Options.php
index 872d1314..0a49372c 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Options.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Options.php
@@ -151,21 +151,21 @@ trait Options
      *
      * @var string|callable|null
      */
-    protected static $formatFunction = null;
+    protected static $formatFunction;
 
     /**
      * Function to call instead of createFromFormat.
      *
      * @var string|callable|null
      */
-    protected static $createFromFormatFunction = null;
+    protected static $createFromFormatFunction;
 
     /**
      * Function to call instead of parse.
      *
      * @var string|callable|null
      */
-    protected static $parseFunction = null;
+    protected static $parseFunction;
 
     /**
      * Indicates if months should be calculated with overflow.
@@ -173,7 +173,7 @@ trait Options
      *
      * @var bool|null
      */
-    protected $localMonthsOverflow = null;
+    protected $localMonthsOverflow;
 
     /**
      * Indicates if years should be calculated with overflow.
@@ -181,7 +181,7 @@ trait Options
      *
      * @var bool|null
      */
-    protected $localYearsOverflow = null;
+    protected $localYearsOverflow;
 
     /**
      * Indicates if the strict mode is in use.
@@ -189,49 +189,49 @@ trait Options
      *
      * @var bool|null
      */
-    protected $localStrictModeEnabled = null;
+    protected $localStrictModeEnabled;
 
     /**
      * Options for diffForHumans and forHumans methods.
      *
      * @var bool|null
      */
-    protected $localHumanDiffOptions = null;
+    protected $localHumanDiffOptions;
 
     /**
      * Format to use on string cast.
      *
      * @var string|null
      */
-    protected $localToStringFormat = null;
+    protected $localToStringFormat;
 
     /**
      * Format to use on JSON serialization.
      *
      * @var string|null
      */
-    protected $localSerializer = null;
+    protected $localSerializer;
 
     /**
      * Instance-specific macros.
      *
      * @var array|null
      */
-    protected $localMacros = null;
+    protected $localMacros;
 
     /**
      * Instance-specific generic macros.
      *
      * @var array|null
      */
-    protected $localGenericMacros = null;
+    protected $localGenericMacros;
 
     /**
      * Function to call instead of format.
      *
      * @var string|callable|null
      */
-    protected $localFormatFunction = null;
+    protected $localFormatFunction;
 
     /**
      * @deprecated To avoid conflict between different third-party libraries, static setters should not be used.
@@ -449,7 +449,7 @@ trait Options
 
     protected function addExtraDebugInfos(&$infos): void
     {
-        if ($this instanceof CarbonInterface || $this instanceof DateTimeInterface) {
+        if ($this instanceof DateTimeInterface) {
             try {
                 if (!isset($infos['date'])) {
                     $infos['date'] = $this->format(CarbonInterface::MOCK_DATETIME_FORMAT);
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Rounding.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Rounding.php
index be8190d8..03d3fe69 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Rounding.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Rounding.php
@@ -194,7 +194,10 @@ trait Rounding
      */
     public function roundWeek($weekStartsAt = null)
     {
-        return $this->closest($this->copy()->floorWeek($weekStartsAt), $this->copy()->ceilWeek($weekStartsAt));
+        return $this->closest(
+            $this->avoidMutation()->floorWeek($weekStartsAt),
+            $this->avoidMutation()->ceilWeek($weekStartsAt)
+        );
     }
 
     /**
@@ -219,7 +222,7 @@ trait Rounding
     public function ceilWeek($weekStartsAt = null)
     {
         if ($this->isMutable()) {
-            $startOfWeek = $this->copy()->startOfWeek($weekStartsAt);
+            $startOfWeek = $this->avoidMutation()->startOfWeek($weekStartsAt);
 
             return $startOfWeek != $this ?
                 $this->startOfWeek($weekStartsAt)->addWeek() :
@@ -230,6 +233,6 @@ trait Rounding
 
         return $startOfWeek != $this ?
             $startOfWeek->addWeek() :
-            $this->copy();
+            $this->avoidMutation();
     }
 }
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Serialization.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Serialization.php
index 54ad447d..a27e4e35 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Serialization.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Serialization.php
@@ -12,6 +12,7 @@ namespace Carbon\Traits;
 
 use Carbon\Exceptions\InvalidFormatException;
 use ReturnTypeWillChange;
+use Throwable;
 
 /**
  * Trait Serialization.
@@ -53,7 +54,15 @@ trait Serialization
      *
      * @var string|null
      */
-    protected $dumpLocale = null;
+    protected $dumpLocale;
+
+    /**
+     * Embed date properties to dump in a dedicated variables so it won't overlap native
+     * DateTime ones.
+     *
+     * @var array|null
+     */
+    protected $dumpDateProperties;
 
     /**
      * Return a serialized string of the instance.
@@ -76,7 +85,7 @@ trait Serialization
      */
     public static function fromSerialized($value)
     {
-        $instance = @unserialize("$value");
+        $instance = @unserialize((string) $value);
 
         if (!$instance instanceof static) {
             throw new InvalidFormatException("Invalid serialized value: $value");
@@ -114,7 +123,7 @@ trait Serialization
      */
     public function __sleep()
     {
-        $properties = $this->dumpProperties;
+        $properties = $this->getSleepProperties();
 
         if ($this->localTranslator ?? null) {
             $properties[] = 'dumpLocale';
@@ -131,7 +140,15 @@ trait Serialization
     public function __wakeup()
     {
         if (get_parent_class() && method_exists(parent::class, '__wakeup')) {
-            parent::__wakeup();
+            // @codeCoverageIgnoreStart
+            try {
+                parent::__wakeup();
+            } catch (Throwable $exception) {
+                // FatalError occurs when calling msgpack_unpack() in PHP 7.4 or later.
+                ['date' => $date, 'timezone' => $timezone] = $this->dumpDateProperties;
+                parent::__construct($date, unserialize($timezone));
+            }
+            // @codeCoverageIgnoreEnd
         }
 
         $this->constructedObjectId = spl_object_hash($this);
@@ -149,6 +166,7 @@ trait Serialization
      *
      * @return array|string
      */
+    #[ReturnTypeWillChange]
     public function jsonSerialize()
     {
         $serializer = $this->localSerializer ?? static::$serializer;
@@ -194,4 +212,26 @@ trait Serialization
 
         return $this;
     }
+
+    private function getSleepProperties(): array
+    {
+        $properties = $this->dumpProperties;
+
+        // @codeCoverageIgnoreStart
+        if (!\extension_loaded('msgpack')) {
+            return $properties;
+        }
+
+        if (isset($this->constructedObjectId)) {
+            $this->dumpDateProperties = [
+                'date' => $this->format('Y-m-d H:i:s.u'),
+                'timezone' => serialize($this->timezone ?? null),
+            ];
+
+            $properties[] = 'dumpDateProperties';
+        }
+
+        return $properties;
+        // @codeCoverageIgnoreEnd
+    }
 }
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Test.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Test.php
index 29338c1a..d9989749 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Test.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Test.php
@@ -63,12 +63,16 @@ trait Test
      *
      * @param Closure|static|string|false|null $testNow real or mock Carbon instance
      * @param Closure|null $callback
+     *
+     * @return mixed
      */
     public static function withTestNow($testNow = null, $callback = null)
     {
         static::setTestNow($testNow);
-        $callback();
+        $result = $callback();
         static::setTestNow();
+
+        return $result;
     }
 
     /**
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Timestamp.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Timestamp.php
index b3b5d5f1..35d45aa5 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Timestamp.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Timestamp.php
@@ -45,6 +45,7 @@ trait Timestamp
         $delta = floor($decimal / static::MICROSECONDS_PER_SECOND);
         $integer += $delta;
         $decimal -= $delta * static::MICROSECONDS_PER_SECOND;
+        $decimal = str_pad((string) $decimal, 6, '0', STR_PAD_LEFT);
 
         return static::rawCreateFromFormat('U u', "$integer $decimal");
     }
@@ -136,6 +137,16 @@ trait Timestamp
         return $this->getPreciseTimestamp(3);
     }
 
+    /**
+     * Returns the timestamp with millisecond precision.
+     *
+     * @return int
+     */
+    public function getTimestampMs()
+    {
+        return (int) $this->getPreciseTimestamp(3);
+    }
+
     /**
      * @alias getTimestamp
      *
@@ -166,15 +177,15 @@ trait Timestamp
             $numbers = number_format($numbers, $decimals, '.', '');
         }
 
-        $sign = substr($numbers, 0, 1) === '-' ? -1 : 1;
+        $sign = str_starts_with($numbers, '-') ? -1 : 1;
         $integer = 0;
         $decimal = 0;
 
         foreach (preg_split('`[^0-9.]+`', $numbers) as $chunk) {
             [$integerPart, $decimalPart] = explode('.', "$chunk.");
 
-            $integer += \intval($integerPart);
-            $decimal += \floatval("0.$decimalPart");
+            $integer += (int) $integerPart;
+            $decimal += (float) ("0.$decimalPart");
         }
 
         $overflow = floor($decimal);
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Units.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Units.php
index c8cd108d..aec85ab2 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Units.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Units.php
@@ -48,7 +48,7 @@ trait Units
                 $seconds = (int) floor($diff / static::MICROSECONDS_PER_SECOND);
                 $time += $seconds;
                 $diff -= $seconds * static::MICROSECONDS_PER_SECOND;
-                $microtime = str_pad("$diff", 6, '0', STR_PAD_LEFT);
+                $microtime = str_pad((string) $diff, 6, '0', STR_PAD_LEFT);
                 $tz = $this->tz;
 
                 return $this->tz('UTC')->modify("@$time.$microtime")->tz($tz);
@@ -201,6 +201,21 @@ trait Units
             $unit = CarbonInterval::make($unit);
         }
 
+        // Can be removed if https://bugs.php.net/bug.php?id=81106
+        // is fixed
+        // @codeCoverageIgnoreStart
+        if (
+            $unit instanceof DateInterval &&
+            version_compare(PHP_VERSION, '8.1.0-dev', '>=') &&
+            ($unit->f < 0 || $unit->f >= 1)
+        ) {
+            $unit = clone $unit;
+            $seconds = floor($unit->f);
+            $unit->f -= $seconds;
+            $unit->s += (int) $seconds;
+        }
+        // @codeCoverageIgnoreEnd
+
         if ($unit instanceof CarbonConverterInterface) {
             return $this->resolveCarbon($unit->convertDate($this, false));
         }
@@ -233,8 +248,8 @@ trait Units
     {
         $date = $this;
 
-        if (!is_numeric($value) || !\floatval($value)) {
-            return $date->isMutable() ? $date : $date->copy();
+        if (!is_numeric($value) || !(float) $value) {
+            return $date->isMutable() ? $date : $date->avoidMutation();
         }
 
         $metaUnits = [
@@ -377,7 +392,7 @@ trait Units
             [$value, $unit] = [$unit, $value];
         }
 
-        return $this->addUnit($unit, -\floatval($value), $overflow);
+        return $this->addUnit($unit, -(float) $value, $overflow);
     }
 
     /**
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Week.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Week.php
index 98ee84a1..64cece7a 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Week.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Traits/Week.php
@@ -27,7 +27,7 @@ namespace Carbon\Traits;
  * @method static addWeeks(int $weeks = 1)
  * @method static copy()
  * @method static dayOfYear(int $dayOfYear)
- * @method string getTranslationMessage(string $key, string $locale = null, string $default = null, $translator = null)
+ * @method string getTranslationMessage(string $key, ?string $locale = null, ?string $default = null, $translator = null)
  * @method static next(int|string $day = null)
  * @method static startOfWeek(int $day = 1)
  * @method static subWeeks(int $weeks = 1)
@@ -75,7 +75,7 @@ trait Week
             $year = (int) round($year);
 
             if ($this->weekYear(null, $dayOfWeek, $dayOfYear) === $year) {
-                return $this->copy();
+                return $this->avoidMutation();
             }
 
             $week = $this->week(null, $dayOfWeek, $dayOfYear);
@@ -103,13 +103,13 @@ trait Week
 
         $year = $this->year;
         $day = $this->dayOfYear;
-        $date = $this->copy()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
+        $date = $this->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
 
         if ($date->year === $year && $day < $date->dayOfYear) {
             return $year - 1;
         }
 
-        $date = $this->copy()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
+        $date = $this->avoidMutation()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
 
         if ($date->year === $year && $day >= $date->dayOfYear) {
             return $year + 1;
@@ -151,12 +151,12 @@ trait Week
         $dayOfWeek = $dayOfWeek ?? $this->getTranslationMessage('first_day_of_week') ?? 0;
         $dayOfYear = $dayOfYear ?? $this->getTranslationMessage('day_of_first_week_of_year') ?? 1;
         $year = $this->year;
-        $start = $this->copy()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
+        $start = $this->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
         $startDay = $start->dayOfYear;
         if ($start->year !== $year) {
             $startDay -= $start->daysInYear;
         }
-        $end = $this->copy()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
+        $end = $this->avoidMutation()->addYear()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
         $endDay = $end->dayOfYear;
         if ($end->year !== $year) {
             $endDay += $this->daysInYear;
@@ -186,8 +186,8 @@ trait Week
             return $date->addWeeks(round($week) - $this->week(null, $dayOfWeek, $dayOfYear));
         }
 
-        $start = $date->copy()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
-        $end = $date->copy()->startOfWeek($dayOfWeek);
+        $start = $date->avoidMutation()->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
+        $end = $date->avoidMutation()->startOfWeek($dayOfWeek);
         if ($start > $end) {
             $start = $start->subWeeks(26)->dayOfYear($dayOfYear)->startOfWeek($dayOfWeek);
         }
diff --git a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Translator.php b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Translator.php
index 3122a85c..9af48ebe 100644
--- a/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Translator.php
+++ b/data/web/inc/lib/vendor/nesbot/carbon/src/Carbon/Translator.php
@@ -148,7 +148,7 @@ class Translator extends Translation\Translator
      */
     public function trans($id, array $parameters = [], $domain = null, $locale = null)
     {
-        if (null === $domain) {
+        if ($domain === null) {
             $domain = 'messages';
         }
 
@@ -326,7 +326,7 @@ class Translator extends Translation\Translator
 
         $previousLocale = $this->getLocale();
 
-        if ($previousLocale === $locale) {
+        if ($previousLocale === $locale && isset($this->messages[$locale])) {
             return true;
         }
 
@@ -355,7 +355,7 @@ class Translator extends Translation\Translator
         }
 
         // If subtag (ex: en_CA) first load the macro (ex: en) to have a fallback
-        if (strpos($locale, '_') !== false &&
+        if (str_contains($locale, '_') &&
             $this->loadMessagesFromFile($macroLocale = preg_replace('/^([^_]+).*$/', '$1', $locale))
         ) {
             parent::setLocale($macroLocale);
diff --git a/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/.github/workflows/main.yml b/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/.github/workflows/main.yml
new file mode 100644
index 00000000..34c8210f
--- /dev/null
+++ b/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/.github/workflows/main.yml
@@ -0,0 +1,60 @@
+name: CI
+
+on: [push]
+
+jobs:
+
+  tests:
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        php: [7.2, 7.3, 7.4, 8.0]
+        dependency-version: [prefer-lowest, prefer-stable]
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v1
+
+      - name: Setup PHP
+        uses: shivammathur/setup-php@v2
+        with:
+          php-version: ${{ matrix.php }}
+          extensions: mailparse
+          coverage: none
+
+      - name: Install dependencies
+        run: composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-suggest --no-progress
+
+      - name: Execute tests
+        run: vendor/bin/phpunit
+
+  php-cs:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v1
+
+      - name: Install dependencies
+        run: composer update --no-progress --ignore-platform-reqs
+
+      - name: Execute phpcs
+        run: vendor/bin/phpcs src tests --standard=psr2
+
+  coverage:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v1
+
+      - name: Setup PHP
+        uses: shivammathur/setup-php@v2
+        with:
+          php-version: 7.4
+          extensions: mailparse
+
+      - name: Install dependencies
+        run: composer update --prefer-dist --no-interaction --no-suggest --no-progress
+
+      - name: Execute code coverage
+        run: |
+          vendor/bin/phpunit --coverage-clover=coverage.xml --whitelist src
+          bash <(curl -s https://codecov.io/bash) -t ${{ secrets.COVERALLS_REPO_TOKEN }}
diff --git a/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/README.md b/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/README.md
index 68f997ae..24a6e0eb 100644
--- a/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/README.md
+++ b/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/README.md
@@ -1,6 +1,6 @@
 # php-mime-mail-parser
 
-A fully tested email parser for PHP 7.1+ (mailparse extension wrapper).
+A fully tested email parser for PHP 7.2+ (mailparse extension wrapper).
 
 It's the most effective php email parser around in terms of performance, foreign character encoding, attachment handling, and ease of use.
 Internet Message Format RFC [822](https://tools.ietf.org/html/rfc822), [2822](https://tools.ietf.org/html/rfc2822), [5322](https://tools.ietf.org/html/rfc5322).
@@ -23,7 +23,7 @@ Yes. All known issues have been reproduced, fixed and tested.
 
 We use GitHub Actions, Codecov, Codacy to help ensure code quality. You can see real-time statistics below:
 
-[![Actions Status](https://wdp9fww0r9.execute-api.us-west-2.amazonaws.com/production/badge/php-mime-mail-parser/php-mime-mail-parser?style=flat-square)](https://wdp9fww0r9.execute-api.us-west-2.amazonaws.com/production/results/php-mime-mail-parser/php-mime-mail-parser)
+[![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fphp-mime-mail-parser%2Fphp-mime-mail-parser%2Fbadge%3Fref%3Dmaster&style=flat-square)](https://actions-badge.atrox.dev/php-mime-mail-parser/php-mime-mail-parser/goto?ref=master)
 [![Coverage](https://img.shields.io/codecov/c/gh/php-mime-mail-parser/php-mime-mail-parser?style=flat-square)](https://codecov.io/gh/php-mime-mail-parser/php-mime-mail-parser)
 [![Code Quality](https://img.shields.io/codacy/grade/4e0e44fee21147ddbdd18ff976251875?style=flat-square)](https://app.codacy.com/app/php-mime-mail-parser/php-mime-mail-parser)
 
@@ -40,19 +40,20 @@ To install the latest version of PHP MIME Mail Parser, run the command below:
 
 The following versions of PHP are supported:
 
-* PHP 7.1
 * PHP 7.2
 * PHP 7.3
+* PHP 7.4
 
 Previous Versions:
 
 | PHP Compatibility  | Version |
 | ------------- | ------------- |
-| HHVM  | php-mime-mail-parser 2.11.1  |
-| PHP 5.4  | php-mime-mail-parser 2.11.1  |
-| PHP 5.5  | php-mime-mail-parser 2.11.1  |
+| HHVM  | php-mime-mail-parser 2.11.1    |
+| PHP 5.4  | php-mime-mail-parser 2.11.1 |
+| PHP 5.5  | php-mime-mail-parser 2.11.1 |
 | PHP 5.6  | php-mime-mail-parser 3.0.4  |
 | PHP 7.0  | php-mime-mail-parser 3.0.4  |
+| PHP 7.1  | php-mime-mail-parser 5.0.5  |
 
 Make sure you have the mailparse extension (http://php.net/manual/en/book.mailparse.php) properly installed. The command line `php -m | grep mailparse` need to return "mailparse".
 
diff --git a/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/composer.json b/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/composer.json
index a797183e..e9861a24 100644
--- a/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/composer.json
+++ b/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/composer.json
@@ -1,7 +1,7 @@
 {
     "name": "php-mime-mail-parser/php-mime-mail-parser",
     "type": "library",
-    "description": "A fully tested email parser for PHP 7.1+ (mailparse extension wrapper).",
+    "description": "A fully tested email parser for PHP 7.2+ (mailparse extension wrapper).",
     "keywords": ["mime", "mail", "mailparse", "MimeMailParser", "parser", "php"],
     "homepage": "https://github.com/php-mime-mail-parser/php-mime-mail-parser",
     "license": "MIT",
@@ -42,14 +42,13 @@
         "url":"https://github.com/php-mime-mail-parser/php-mime-mail-parser.git"
     },
     "require": {
-        "php":           "^7.1",
+        "php":           "^7.2|^8.0",
         "ext-mailparse": "*"
     },
     "require-dev": {
-        "phpunit/phpunit":              "^7.0",
-        "phpunit/php-token-stream":     "^3.0",
-        "php-coveralls/php-coveralls":  "^2.1",
-        "squizlabs/php_codesniffer":    "^3.4"
+        "phpunit/phpunit":              "^8.0",
+        "php-coveralls/php-coveralls":  "^2.2",
+        "squizlabs/php_codesniffer":    "^3.5"
     },
     "replace": {
         "exorus/php-mime-mail-parser":   "*",
diff --git a/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Mbstring.php b/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Mbstring.php
index c31611fb..b5990956 100644
--- a/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Mbstring.php
+++ b/data/web/inc/lib/vendor/symfony/polyfill-mbstring/Mbstring.php
@@ -69,14 +69,15 @@ final class Mbstring
 {
     public const MB_CASE_FOLD = \PHP_INT_MAX;
 
-    private static $encodingList = ['ASCII', 'UTF-8'];
-    private static $language = 'neutral';
-    private static $internalEncoding = 'UTF-8';
-    private static $caseFold = [
+    private const CASE_FOLD = [
         ['µ', 'ſ', "\xCD\x85", 'ς', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"],
         ['μ', 's', 'ι',        'σ', 'β',        'θ',        'φ',        'π',        'κ',        'ρ',        'ε',        "\xE1\xB9\xA1", 'ι'],
     ];
 
+    private static $encodingList = ['ASCII', 'UTF-8'];
+    private static $language = 'neutral';
+    private static $internalEncoding = 'UTF-8';
+
     public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
     {
         if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
@@ -300,7 +301,7 @@ final class Mbstring
                 $map = $upper;
             } else {
                 if (self::MB_CASE_FOLD === $mode) {
-                    $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
+                    $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s);
                 }
 
                 static $lower = null;
diff --git a/data/web/inc/lib/vendor/symfony/polyfill-php80/README.md b/data/web/inc/lib/vendor/symfony/polyfill-php80/README.md
index eaa3050a..10b8ee49 100644
--- a/data/web/inc/lib/vendor/symfony/polyfill-php80/README.md
+++ b/data/web/inc/lib/vendor/symfony/polyfill-php80/README.md
@@ -16,7 +16,7 @@ This component provides features added to PHP 8.0 core:
 - [`get_resource_id`](https://php.net/get_resource_id)
 
 More information can be found in the
-[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md).
+[main Polyfill README](https://github.com/symfony/polyfill/blob/main/README.md).
 
 License
 =======
diff --git a/data/web/inc/lib/vendor/symfony/polyfill-php80/bootstrap.php b/data/web/inc/lib/vendor/symfony/polyfill-php80/bootstrap.php
index 4f791f9e..e5f7dbc1 100644
--- a/data/web/inc/lib/vendor/symfony/polyfill-php80/bootstrap.php
+++ b/data/web/inc/lib/vendor/symfony/polyfill-php80/bootstrap.php
@@ -26,13 +26,13 @@ if (!function_exists('preg_last_error_msg')) {
     function preg_last_error_msg(): string { return p\Php80::preg_last_error_msg(); }
 }
 if (!function_exists('str_contains')) {
-    function str_contains(string $haystack, string $needle): bool { return p\Php80::str_contains($haystack, $needle); }
+    function str_contains(?string $haystack, ?string $needle): bool { return p\Php80::str_contains($haystack ?? '', $needle ?? ''); }
 }
 if (!function_exists('str_starts_with')) {
-    function str_starts_with(string $haystack, string $needle): bool { return p\Php80::str_starts_with($haystack, $needle); }
+    function str_starts_with(?string $haystack, ?string $needle): bool { return p\Php80::str_starts_with($haystack ?? '', $needle ?? ''); }
 }
 if (!function_exists('str_ends_with')) {
-    function str_ends_with(string $haystack, string $needle): bool { return p\Php80::str_ends_with($haystack, $needle); }
+    function str_ends_with(?string $haystack, ?string $needle): bool { return p\Php80::str_ends_with($haystack ?? '', $needle ?? ''); }
 }
 if (!function_exists('get_debug_type')) {
     function get_debug_type($value): string { return p\Php80::get_debug_type($value); }
diff --git a/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPushCommand.php b/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPushCommand.php
index da265d6c..b28d3e10 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPushCommand.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Command/TranslationPushCommand.php
@@ -94,13 +94,13 @@ EOF
      */
     protected function execute(InputInterface $input, OutputInterface $output): int
     {
+        $provider = $this->providers->get($input->getArgument('provider'));
+
         if (!$this->enabledLocales) {
-            throw new InvalidArgumentException('You must define "framework.translator.enabled_locales" or "framework.translator.providers.%s.locales" config key in order to work with translation providers.');
+            throw new InvalidArgumentException(sprintf('You must define "framework.translator.enabled_locales" or "framework.translator.providers.%s.locales" config key in order to work with translation providers.', parse_url($provider, \PHP_URL_SCHEME)));
         }
 
         $io = new SymfonyStyle($input, $output);
-
-        $provider = $this->providers->get($input->getArgument('provider'));
         $domains = $input->getOption('domains');
         $locales = $input->getOption('locales');
         $force = $input->getOption('force');
diff --git a/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php b/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php
index 18c02488..85b0fa48 100644
--- a/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php
+++ b/data/web/inc/lib/vendor/symfony/translation/DependencyInjection/TranslatorPathsPass.php
@@ -64,6 +64,9 @@ class TranslatorPathsPass extends AbstractRecursivePass
             foreach ($this->paths as $class => $_) {
                 if (($r = $container->getReflectionClass($class)) && !$r->isInterface()) {
                     $paths[] = $r->getFileName();
+                    foreach ($r->getTraits() as $trait) {
+                        $paths[] = $trait->getFileName();
+                    }
                 }
             }
             if ($paths) {
diff --git a/data/web/inc/lib/vendor/symfony/translation/Dumper/XliffFileDumper.php b/data/web/inc/lib/vendor/symfony/translation/Dumper/XliffFileDumper.php
index 7d0a4464..f7dbdcdd 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Dumper/XliffFileDumper.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Dumper/XliffFileDumper.php
@@ -141,8 +141,8 @@ class XliffFileDumper extends FileDumper
         $xliff->setAttribute('trgLang', str_replace('_', '-', $messages->getLocale()));
 
         $xliffFile = $xliff->appendChild($dom->createElement('file'));
-        if (MessageCatalogue::INTL_DOMAIN_SUFFIX === substr($domain, -($suffixLength = \strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX)))) {
-            $xliffFile->setAttribute('id', substr($domain, 0, -$suffixLength).'.'.$messages->getLocale());
+        if (str_ends_with($domain, MessageCatalogue::INTL_DOMAIN_SUFFIX)) {
+            $xliffFile->setAttribute('id', substr($domain, 0, -\strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX)).'.'.$messages->getLocale());
         } else {
             $xliffFile->setAttribute('id', $domain.'.'.$messages->getLocale());
         }
@@ -198,6 +198,6 @@ class XliffFileDumper extends FileDumper
 
     private function hasMetadataArrayInfo(string $key, array $metadata = null): bool
     {
-        return null !== $metadata && \array_key_exists($key, $metadata) && ($metadata[$key] instanceof \Traversable || \is_array($metadata[$key]));
+        return is_iterable($metadata[$key] ?? null);
     }
 }
diff --git a/data/web/inc/lib/vendor/symfony/translation/Exception/IncompleteDsnException.php b/data/web/inc/lib/vendor/symfony/translation/Exception/IncompleteDsnException.php
index 192de3c6..cb0ce027 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Exception/IncompleteDsnException.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Exception/IncompleteDsnException.php
@@ -13,7 +13,7 @@ namespace Symfony\Component\Translation\Exception;
 
 class IncompleteDsnException extends InvalidArgumentException
 {
-    public function __construct(string $message, string $dsn = null, ?\Throwable $previous = null)
+    public function __construct(string $message, string $dsn = null, \Throwable $previous = null)
     {
         if ($dsn) {
             $message = sprintf('Invalid "%s" provider DSN: ', $dsn).$message;
diff --git a/data/web/inc/lib/vendor/symfony/translation/Exception/MissingRequiredOptionException.php b/data/web/inc/lib/vendor/symfony/translation/Exception/MissingRequiredOptionException.php
index e17283dc..2b5f8080 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Exception/MissingRequiredOptionException.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Exception/MissingRequiredOptionException.php
@@ -16,7 +16,7 @@ namespace Symfony\Component\Translation\Exception;
  */
 class MissingRequiredOptionException extends IncompleteDsnException
 {
-    public function __construct(string $option, string $dsn = null, ?\Throwable $previous = null)
+    public function __construct(string $option, string $dsn = null, \Throwable $previous = null)
     {
         $message = sprintf('The option "%s" is required but missing.', $option);
 
diff --git a/data/web/inc/lib/vendor/symfony/translation/Extractor/ChainExtractor.php b/data/web/inc/lib/vendor/symfony/translation/Extractor/ChainExtractor.php
index 6b6e1827..95dcf157 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Extractor/ChainExtractor.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Extractor/ChainExtractor.php
@@ -29,8 +29,6 @@ class ChainExtractor implements ExtractorInterface
 
     /**
      * Adds a loader to the translation extractor.
-     *
-     * @param string $format The format of the loader
      */
     public function addExtractor(string $format, ExtractorInterface $extractor)
     {
diff --git a/data/web/inc/lib/vendor/symfony/translation/Extractor/ExtractorInterface.php b/data/web/inc/lib/vendor/symfony/translation/Extractor/ExtractorInterface.php
index 718858ee..e1db8a9c 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Extractor/ExtractorInterface.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Extractor/ExtractorInterface.php
@@ -24,14 +24,12 @@ interface ExtractorInterface
     /**
      * Extracts translation messages from files, a file or a directory to the catalogue.
      *
-     * @param string|string[] $resource Files, a file or a directory
+     * @param string|iterable<string> $resource Files, a file or a directory
      */
     public function extract($resource, MessageCatalogue $catalogue);
 
     /**
      * Sets the prefix that should be used for new found messages.
-     *
-     * @param string $prefix The prefix
      */
     public function setPrefix(string $prefix);
 }
diff --git a/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpStringTokenParser.php b/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpStringTokenParser.php
index e68b0e59..1d82caf2 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpStringTokenParser.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Extractor/PhpStringTokenParser.php
@@ -133,7 +133,7 @@ class PhpStringTokenParser
         $str = preg_replace('~(\r\n|\n|\r)$~', '', $str);
 
         // nowdoc string
-        if (false !== strpos($startToken, '\'')) {
+        if (str_contains($startToken, '\'')) {
             return $str;
         }
 
diff --git a/data/web/inc/lib/vendor/symfony/translation/Loader/CsvFileLoader.php b/data/web/inc/lib/vendor/symfony/translation/Loader/CsvFileLoader.php
index 25ac2f56..8d5d4db9 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Loader/CsvFileLoader.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Loader/CsvFileLoader.php
@@ -27,7 +27,7 @@ class CsvFileLoader extends FileLoader
     /**
      * {@inheritdoc}
      */
-    protected function loadResource($resource)
+    protected function loadResource(string $resource)
     {
         $messages = [];
 
diff --git a/data/web/inc/lib/vendor/symfony/translation/Loader/FileLoader.php b/data/web/inc/lib/vendor/symfony/translation/Loader/FileLoader.php
index 2ffba392..4725ea6d 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Loader/FileLoader.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Loader/FileLoader.php
@@ -55,11 +55,9 @@ abstract class FileLoader extends ArrayLoader
     }
 
     /**
-     * @param string $resource
-     *
      * @return array
      *
      * @throws InvalidResourceException if stream content has an invalid format
      */
-    abstract protected function loadResource($resource);
+    abstract protected function loadResource(string $resource);
 }
diff --git a/data/web/inc/lib/vendor/symfony/translation/Loader/IniFileLoader.php b/data/web/inc/lib/vendor/symfony/translation/Loader/IniFileLoader.php
index 11d9b272..7398f777 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Loader/IniFileLoader.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Loader/IniFileLoader.php
@@ -21,7 +21,7 @@ class IniFileLoader extends FileLoader
     /**
      * {@inheritdoc}
      */
-    protected function loadResource($resource)
+    protected function loadResource(string $resource)
     {
         return parse_ini_file($resource, true);
     }
diff --git a/data/web/inc/lib/vendor/symfony/translation/Loader/JsonFileLoader.php b/data/web/inc/lib/vendor/symfony/translation/Loader/JsonFileLoader.php
index 8a8996b0..5aefba07 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Loader/JsonFileLoader.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Loader/JsonFileLoader.php
@@ -23,7 +23,7 @@ class JsonFileLoader extends FileLoader
     /**
      * {@inheritdoc}
      */
-    protected function loadResource($resource)
+    protected function loadResource(string $resource)
     {
         $messages = [];
         if ($data = file_get_contents($resource)) {
diff --git a/data/web/inc/lib/vendor/symfony/translation/Loader/MoFileLoader.php b/data/web/inc/lib/vendor/symfony/translation/Loader/MoFileLoader.php
index accd023a..0ff6549d 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Loader/MoFileLoader.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Loader/MoFileLoader.php
@@ -41,7 +41,7 @@ class MoFileLoader extends FileLoader
      *
      * {@inheritdoc}
      */
-    protected function loadResource($resource)
+    protected function loadResource(string $resource)
     {
         $stream = fopen($resource, 'r');
 
@@ -89,7 +89,7 @@ class MoFileLoader extends FileLoader
             fseek($stream, $offset);
             $singularId = fread($stream, $length);
 
-            if (false !== strpos($singularId, "\000")) {
+            if (str_contains($singularId, "\000")) {
                 [$singularId, $pluralId] = explode("\000", $singularId);
             }
 
@@ -104,7 +104,7 @@ class MoFileLoader extends FileLoader
             fseek($stream, $offset);
             $translated = fread($stream, $length);
 
-            if (false !== strpos($translated, "\000")) {
+            if (str_contains($translated, "\000")) {
                 $translated = explode("\000", $translated);
             }
 
diff --git a/data/web/inc/lib/vendor/symfony/translation/Loader/PhpFileLoader.php b/data/web/inc/lib/vendor/symfony/translation/Loader/PhpFileLoader.php
index c361d529..85f10902 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Loader/PhpFileLoader.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Loader/PhpFileLoader.php
@@ -23,7 +23,7 @@ class PhpFileLoader extends FileLoader
     /**
      * {@inheritdoc}
      */
-    protected function loadResource($resource)
+    protected function loadResource(string $resource)
     {
         if ([] === self::$cache && \function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN) && (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) || filter_var(ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN))) {
             self::$cache = null;
diff --git a/data/web/inc/lib/vendor/symfony/translation/Loader/PoFileLoader.php b/data/web/inc/lib/vendor/symfony/translation/Loader/PoFileLoader.php
index 5e460fbf..ee143e20 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Loader/PoFileLoader.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Loader/PoFileLoader.php
@@ -60,7 +60,7 @@ class PoFileLoader extends FileLoader
      *
      * {@inheritdoc}
      */
-    protected function loadResource($resource)
+    protected function loadResource(string $resource)
     {
         $stream = fopen($resource, 'r');
 
diff --git a/data/web/inc/lib/vendor/symfony/translation/Loader/XliffFileLoader.php b/data/web/inc/lib/vendor/symfony/translation/Loader/XliffFileLoader.php
index 7c0ac8ae..35ad33ef 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Loader/XliffFileLoader.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Loader/XliffFileLoader.php
@@ -75,7 +75,7 @@ class XliffFileLoader implements LoaderInterface
         return $catalogue;
     }
 
-    private function extract($dom, MessageCatalogue $catalogue, string $domain)
+    private function extract(\DOMDocument $dom, MessageCatalogue $catalogue, string $domain)
     {
         $xliffVersion = XliffUtils::getVersionNumber($dom);
 
diff --git a/data/web/inc/lib/vendor/symfony/translation/Loader/YamlFileLoader.php b/data/web/inc/lib/vendor/symfony/translation/Loader/YamlFileLoader.php
index b03c7b77..8588e186 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Loader/YamlFileLoader.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Loader/YamlFileLoader.php
@@ -29,7 +29,7 @@ class YamlFileLoader extends FileLoader
     /**
      * {@inheritdoc}
      */
-    protected function loadResource($resource)
+    protected function loadResource(string $resource)
     {
         if (null === $this->yamlParser) {
             if (!class_exists(\Symfony\Component\Yaml\Parser::class)) {
diff --git a/data/web/inc/lib/vendor/symfony/translation/MessageCatalogue.php b/data/web/inc/lib/vendor/symfony/translation/MessageCatalogue.php
index 1dc3cc54..ff49b5a9 100644
--- a/data/web/inc/lib/vendor/symfony/translation/MessageCatalogue.php
+++ b/data/web/inc/lib/vendor/symfony/translation/MessageCatalogue.php
@@ -27,8 +27,7 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf
     private $parent;
 
     /**
-     * @param string $locale   The locale
-     * @param array  $messages An array of messages classified by domain
+     * @param array $messages An array of messages classified by domain
      */
     public function __construct(string $locale, array $messages = [])
     {
@@ -50,11 +49,10 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf
     public function getDomains()
     {
         $domains = [];
-        $suffixLength = \strlen(self::INTL_DOMAIN_SUFFIX);
 
         foreach ($this->messages as $domain => $messages) {
-            if (\strlen($domain) > $suffixLength && false !== $i = strpos($domain, self::INTL_DOMAIN_SUFFIX, -$suffixLength)) {
-                $domain = substr($domain, 0, $i);
+            if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) {
+                $domain = substr($domain, 0, -\strlen(self::INTL_DOMAIN_SUFFIX));
             }
             $domains[$domain] = $domain;
         }
@@ -69,7 +67,7 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf
     {
         if (null !== $domain) {
             // skip messages merge if intl-icu requested explicitly
-            if (false !== strpos($domain, self::INTL_DOMAIN_SUFFIX)) {
+            if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) {
                 return $this->messages[$domain] ?? [];
             }
 
@@ -77,11 +75,10 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf
         }
 
         $allMessages = [];
-        $suffixLength = \strlen(self::INTL_DOMAIN_SUFFIX);
 
         foreach ($this->messages as $domain => $messages) {
-            if (\strlen($domain) > $suffixLength && false !== $i = strpos($domain, self::INTL_DOMAIN_SUFFIX, -$suffixLength)) {
-                $domain = substr($domain, 0, $i);
+            if (str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) {
+                $domain = substr($domain, 0, -\strlen(self::INTL_DOMAIN_SUFFIX));
                 $allMessages[$domain] = $messages + ($allMessages[$domain] ?? []);
             } else {
                 $allMessages[$domain] = ($allMessages[$domain] ?? []) + $messages;
@@ -162,8 +159,7 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf
             $this->messages[$domain] = [];
         }
         $intlDomain = $domain;
-        $suffixLength = \strlen(self::INTL_DOMAIN_SUFFIX);
-        if (\strlen($domain) < $suffixLength || false === strpos($domain, self::INTL_DOMAIN_SUFFIX, -$suffixLength)) {
+        if (!str_ends_with($domain, self::INTL_DOMAIN_SUFFIX)) {
             $intlDomain .= self::INTL_DOMAIN_SUFFIX;
         }
         foreach ($messages as $id => $message) {
diff --git a/data/web/inc/lib/vendor/symfony/translation/MetadataAwareInterface.php b/data/web/inc/lib/vendor/symfony/translation/MetadataAwareInterface.php
index d157a072..2216eed9 100644
--- a/data/web/inc/lib/vendor/symfony/translation/MetadataAwareInterface.php
+++ b/data/web/inc/lib/vendor/symfony/translation/MetadataAwareInterface.php
@@ -25,9 +25,6 @@ interface MetadataAwareInterface
      * domain and then by key. Passing an empty key will return an array with all
      * metadata for the given domain.
      *
-     * @param string $key    The key
-     * @param string $domain The domain name
-     *
      * @return mixed The value that was set or an array with the domains/keys or null
      */
     public function getMetadata(string $key = '', string $domain = 'messages');
@@ -35,9 +32,7 @@ interface MetadataAwareInterface
     /**
      * Adds metadata to a message domain.
      *
-     * @param string $key    The key
-     * @param mixed  $value  The value
-     * @param string $domain The domain name
+     * @param mixed $value
      */
     public function setMetadata(string $key, $value, string $domain = 'messages');
 
@@ -46,9 +41,6 @@ interface MetadataAwareInterface
      *
      * Passing an empty domain will delete all metadata. Passing an empty key will
      * delete all metadata for the given domain.
-     *
-     * @param string $key    The key
-     * @param string $domain The domain name
      */
     public function deleteMetadata(string $key = '', string $domain = 'messages');
 }
diff --git a/data/web/inc/lib/vendor/symfony/translation/Resources/bin/translation-status.php b/data/web/inc/lib/vendor/symfony/translation/Resources/bin/translation-status.php
index e3e64496..4e0723bb 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Resources/bin/translation-status.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Resources/bin/translation-status.php
@@ -52,7 +52,7 @@ if ($argc > 3) {
 }
 
 foreach (array_slice($argv, 1) as $argumentOrOption) {
-    if (0 === strpos($argumentOrOption, '-')) {
+    if (str_starts_with($argumentOrOption, '-')) {
         $config['verbose_output'] = true;
     } else {
         $config['locale_to_analyze'] = $argumentOrOption;
diff --git a/data/web/inc/lib/vendor/symfony/translation/Translator.php b/data/web/inc/lib/vendor/symfony/translation/Translator.php
index b4954dae..9a639561 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Translator.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Translator.php
@@ -134,6 +134,7 @@ class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleA
         }
 
         $this->assertValidLocale($locale);
+        $locale ?: $locale = class_exists(\Locale::class) ? \Locale::getDefault() : 'en';
 
         $this->resources[$locale][] = [$format, $resource, $domain];
 
@@ -150,7 +151,7 @@ class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleA
     public function setLocale(string $locale)
     {
         $this->assertValidLocale($locale);
-        $this->locale = $locale ?? (class_exists(\Locale::class) ? \Locale::getDefault() : 'en');
+        $this->locale = $locale;
     }
 
     /**
@@ -158,14 +159,12 @@ class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleA
      */
     public function getLocale()
     {
-        return $this->locale;
+        return $this->locale ?: (class_exists(\Locale::class) ? \Locale::getDefault() : 'en');
     }
 
     /**
      * Sets the fallback locales.
      *
-     * @param array $locales The fallback locales
-     *
      * @throws InvalidArgumentException If a locale contains invalid characters
      */
     public function setFallbackLocales(array $locales)
@@ -230,7 +229,7 @@ class Translator implements TranslatorInterface, TranslatorBagInterface, LocaleA
      */
     public function getCatalogue(string $locale = null)
     {
-        if (null === $locale) {
+        if (!$locale) {
             $locale = $this->getLocale();
         } else {
             $this->assertValidLocale($locale);
@@ -454,7 +453,7 @@ EOF
      */
     protected function assertValidLocale(string $locale)
     {
-        if (null !== $locale && 1 !== preg_match('/^[a-z0-9@_\\.\\-]*$/i', $locale)) {
+        if (!preg_match('/^[a-z0-9@_\\.\\-]*$/i', (string) $locale)) {
             throw new InvalidArgumentException(sprintf('Invalid "%s" locale.', $locale));
         }
     }
diff --git a/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriter.php b/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriter.php
index e0260b7a..0a349b82 100644
--- a/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriter.php
+++ b/data/web/inc/lib/vendor/symfony/translation/Writer/TranslationWriter.php
@@ -27,10 +27,8 @@ class TranslationWriter implements TranslationWriterInterface
 
     /**
      * Adds a dumper to the writer.
-     *
-     * @param string $format The format of the dumper
      */
-    public function addDumper($format, DumperInterface $dumper)
+    public function addDumper(string $format, DumperInterface $dumper)
     {
         $this->dumpers[$format] = $dumper;
     }
diff --git a/data/web/inc/lib/vendor/symfony/translation/composer.json b/data/web/inc/lib/vendor/symfony/translation/composer.json
index 01c05bd7..de84e165 100644
--- a/data/web/inc/lib/vendor/symfony/translation/composer.json
+++ b/data/web/inc/lib/vendor/symfony/translation/composer.json
@@ -19,7 +19,7 @@
         "php": ">=7.2.5",
         "symfony/deprecation-contracts": "^2.1",
         "symfony/polyfill-mbstring": "~1.0",
-        "symfony/polyfill-php80": "^1.15",
+        "symfony/polyfill-php80": "^1.16",
         "symfony/translation-contracts": "^2.3"
     },
     "require-dev": {
@@ -32,7 +32,7 @@
         "symfony/service-contracts": "^1.1.2|^2",
         "symfony/yaml": "^4.4|^5.0",
         "symfony/finder": "^4.4|^5.0",
-        "psr/log": "~1.0"
+        "psr/log": "^1|^2|^3"
     },
     "conflict": {
         "symfony/config": "<4.4",
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ClassStub.php b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ClassStub.php
index 612a7ca2..48f84835 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ClassStub.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ClassStub.php
@@ -55,7 +55,7 @@ class ClassStub extends ConstStub
                 }
             }
 
-            if (false !== strpos($identifier, "@anonymous\0")) {
+            if (str_contains($identifier, "@anonymous\0")) {
                 $this->value = $identifier = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
                     return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0];
                 }, $identifier);
@@ -65,7 +65,7 @@ class ClassStub extends ConstStub
                 $s = ReflectionCaster::castFunctionAbstract($r, [], new Stub(), true, Caster::EXCLUDE_VERBOSE);
                 $s = ReflectionCaster::getSignature($s);
 
-                if ('()' === substr($identifier, -2)) {
+                if (str_ends_with($identifier, '()')) {
                     $this->value = substr_replace($identifier, $s, -2);
                 } else {
                     $this->value .= $s;
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DOMCaster.php b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DOMCaster.php
index 5644e489..4dd16e0e 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DOMCaster.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/DOMCaster.php
@@ -82,7 +82,7 @@ class DOMCaster
         return $a;
     }
 
-    public static function castImplementation($dom, array $a, Stub $stub, bool $isNested)
+    public static function castImplementation(\DOMImplementation $dom, array $a, Stub $stub, bool $isNested)
     {
         $a += [
             Caster::PREFIX_VIRTUAL.'Core' => '1.0',
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ExceptionCaster.php b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ExceptionCaster.php
index 437db26d..baa7a180 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ExceptionCaster.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ExceptionCaster.php
@@ -149,7 +149,7 @@ class ExceptionCaster
             $f = self::castFrameStub($frame, [], $frame, true);
             if (isset($f[$prefix.'src'])) {
                 foreach ($f[$prefix.'src']->value as $label => $frame) {
-                    if (0 === strpos($label, "\0~collapse=0")) {
+                    if (str_starts_with($label, "\0~collapse=0")) {
                         if ($collapse) {
                             $label = substr_replace($label, '1', 11, 1);
                         } else {
@@ -281,7 +281,7 @@ class ExceptionCaster
         }
         unset($a[$xPrefix.'string'], $a[Caster::PREFIX_DYNAMIC.'xdebug_message'], $a[Caster::PREFIX_DYNAMIC.'__destructorException']);
 
-        if (isset($a[Caster::PREFIX_PROTECTED.'message']) && false !== strpos($a[Caster::PREFIX_PROTECTED.'message'], "@anonymous\0")) {
+        if (isset($a[Caster::PREFIX_PROTECTED.'message']) && str_contains($a[Caster::PREFIX_PROTECTED.'message'], "@anonymous\0")) {
             $a[Caster::PREFIX_PROTECTED.'message'] = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
                 return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0];
             }, $a[Caster::PREFIX_PROTECTED.'message']);
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/LinkStub.php b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/LinkStub.php
index 0aa076a2..7e078033 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/LinkStub.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/LinkStub.php
@@ -23,7 +23,7 @@ class LinkStub extends ConstStub
     private static $vendorRoots;
     private static $composerRoots;
 
-    public function __construct($label, int $line = 0, $href = null)
+    public function __construct(string $label, int $line = 0, string $href = null)
     {
         $this->value = $label;
 
@@ -33,12 +33,12 @@ class LinkStub extends ConstStub
         if (!\is_string($href)) {
             return;
         }
-        if (0 === strpos($href, 'file://')) {
+        if (str_starts_with($href, 'file://')) {
             if ($href === $label) {
                 $label = substr($label, 7);
             }
             $href = substr($href, 7);
-        } elseif (false !== strpos($href, '://')) {
+        } elseif (str_contains($href, '://')) {
             $this->attr['href'] = $href;
 
             return;
@@ -69,7 +69,7 @@ class LinkStub extends ConstStub
             self::$vendorRoots = [];
 
             foreach (get_declared_classes() as $class) {
-                if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) {
+                if ('C' === $class[0] && str_starts_with($class, 'ComposerAutoloaderInit')) {
                     $r = new \ReflectionClass($class);
                     $v = \dirname($r->getFileName(), 2);
                     if (is_file($v.'/composer/installed.json')) {
@@ -85,7 +85,7 @@ class LinkStub extends ConstStub
         }
 
         foreach (self::$vendorRoots as $root) {
-            if ($inVendor = 0 === strpos($file, $root)) {
+            if ($inVendor = str_starts_with($file, $root)) {
                 return $root;
             }
         }
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/MemcachedCaster.php b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/MemcachedCaster.php
index 111b0607..cfef19ac 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/MemcachedCaster.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/MemcachedCaster.php
@@ -71,7 +71,7 @@ class MemcachedCaster
 
         $optionConstants = [];
         foreach ($reflectedMemcached->getConstants() as $constantKey => $value) {
-            if (0 === strpos($constantKey, 'OPT_')) {
+            if (str_starts_with($constantKey, 'OPT_')) {
                 $optionConstants[$constantKey] = $value;
             }
         }
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/RdKafkaCaster.php b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/RdKafkaCaster.php
index c3e4eb9f..db4bba8d 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/RdKafkaCaster.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/RdKafkaCaster.php
@@ -31,7 +31,7 @@ use Symfony\Component\VarDumper\Cloner\Stub;
  */
 class RdKafkaCaster
 {
-    public static function castKafkaConsumer(KafkaConsumer $c, array $a, Stub $stub, $isNested)
+    public static function castKafkaConsumer(KafkaConsumer $c, array $a, Stub $stub, bool $isNested)
     {
         $prefix = Caster::PREFIX_VIRTUAL;
 
@@ -51,7 +51,7 @@ class RdKafkaCaster
         return $a;
     }
 
-    public static function castTopic(Topic $c, array $a, Stub $stub, $isNested)
+    public static function castTopic(Topic $c, array $a, Stub $stub, bool $isNested)
     {
         $prefix = Caster::PREFIX_VIRTUAL;
 
@@ -75,7 +75,7 @@ class RdKafkaCaster
         return $a;
     }
 
-    public static function castMessage(Message $c, array $a, Stub $stub, $isNested)
+    public static function castMessage(Message $c, array $a, Stub $stub, bool $isNested)
     {
         $prefix = Caster::PREFIX_VIRTUAL;
 
@@ -86,7 +86,7 @@ class RdKafkaCaster
         return $a;
     }
 
-    public static function castConf(Conf $c, array $a, Stub $stub, $isNested)
+    public static function castConf(Conf $c, array $a, Stub $stub, bool $isNested)
     {
         $prefix = Caster::PREFIX_VIRTUAL;
 
@@ -97,7 +97,7 @@ class RdKafkaCaster
         return $a;
     }
 
-    public static function castTopicConf(TopicConf $c, array $a, Stub $stub, $isNested)
+    public static function castTopicConf(TopicConf $c, array $a, Stub $stub, bool $isNested)
     {
         $prefix = Caster::PREFIX_VIRTUAL;
 
@@ -108,7 +108,7 @@ class RdKafkaCaster
         return $a;
     }
 
-    public static function castRdKafka(\RdKafka $c, array $a, Stub $stub, $isNested)
+    public static function castRdKafka(\RdKafka $c, array $a, Stub $stub, bool $isNested)
     {
         $prefix = Caster::PREFIX_VIRTUAL;
 
@@ -121,14 +121,14 @@ class RdKafkaCaster
         return $a;
     }
 
-    public static function castCollectionMetadata(CollectionMetadata $c, array $a, Stub $stub, $isNested)
+    public static function castCollectionMetadata(CollectionMetadata $c, array $a, Stub $stub, bool $isNested)
     {
         $a += iterator_to_array($c);
 
         return $a;
     }
 
-    public static function castTopicMetadata(TopicMetadata $c, array $a, Stub $stub, $isNested)
+    public static function castTopicMetadata(TopicMetadata $c, array $a, Stub $stub, bool $isNested)
     {
         $prefix = Caster::PREFIX_VIRTUAL;
 
@@ -140,7 +140,7 @@ class RdKafkaCaster
         return $a;
     }
 
-    public static function castPartitionMetadata(PartitionMetadata $c, array $a, Stub $stub, $isNested)
+    public static function castPartitionMetadata(PartitionMetadata $c, array $a, Stub $stub, bool $isNested)
     {
         $prefix = Caster::PREFIX_VIRTUAL;
 
@@ -153,7 +153,7 @@ class RdKafkaCaster
         return $a;
     }
 
-    public static function castBrokerMetadata(BrokerMetadata $c, array $a, Stub $stub, $isNested)
+    public static function castBrokerMetadata(BrokerMetadata $c, array $a, Stub $stub, bool $isNested)
     {
         $prefix = Caster::PREFIX_VIRTUAL;
 
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ReflectionCaster.php b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ReflectionCaster.php
index c850e0b1..1781f469 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ReflectionCaster.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ReflectionCaster.php
@@ -42,7 +42,7 @@ class ReflectionCaster
 
         $a = static::castFunctionAbstract($c, $a, $stub, $isNested, $filter);
 
-        if (false === strpos($c->name, '{closure}')) {
+        if (!str_contains($c->name, '{closure}')) {
             $stub->class = isset($a[$prefix.'class']) ? $a[$prefix.'class']->value.'::'.$c->name : $c->name;
             unset($a[$prefix.'class']);
         }
@@ -102,7 +102,7 @@ class ReflectionCaster
                 $prefix.'allowsNull' => $c->allowsNull(),
                 $prefix.'isBuiltin' => $c->isBuiltin(),
             ];
-        } elseif ($c instanceof \ReflectionUnionType) {
+        } elseif ($c instanceof \ReflectionUnionType || $c instanceof \ReflectionIntersectionType) {
             $a[$prefix.'allowsNull'] = $c->allowsNull();
             self::addMap($a, $c, [
                 'types' => 'getTypes',
@@ -381,7 +381,7 @@ class ReflectionCaster
                 } elseif (\is_array($v)) {
                     $signature .= $v ? '[…'.\count($v).']' : '[]';
                 } elseif (\is_string($v)) {
-                    $signature .= 10 > \strlen($v) && false === strpos($v, '\\') ? "'{$v}'" : "'…".\strlen($v)."'";
+                    $signature .= 10 > \strlen($v) && !str_contains($v, '\\') ? "'{$v}'" : "'…".\strlen($v)."'";
                 } elseif (\is_bool($v)) {
                     $signature .= $v ? 'true' : 'false';
                 } else {
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ResourceCaster.php b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ResourceCaster.php
index 6b2ed522..6ae90852 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ResourceCaster.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/ResourceCaster.php
@@ -48,7 +48,7 @@ class ResourceCaster
     public static function castStream($stream, array $a, Stub $stub, bool $isNested)
     {
         $a = stream_get_meta_data($stream) + static::castStreamContext($stream, $a, $stub, $isNested);
-        if (isset($a['uri'])) {
+        if ($a['uri'] ?? false) {
             $a['uri'] = new LinkStub($a['uri']);
         }
 
@@ -60,7 +60,7 @@ class ResourceCaster
         return @stream_context_get_params($stream) ?: $a;
     }
 
-    public static function castGd($gd, array $a, Stub $stub, $isNested)
+    public static function castGd($gd, array $a, Stub $stub, bool $isNested)
     {
         $a['size'] = imagesx($gd).'x'.imagesy($gd);
         $a['trueColor'] = imageistruecolor($gd);
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/SplCaster.php b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/SplCaster.php
index 07f053e4..07f44511 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Caster/SplCaster.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Caster/SplCaster.php
@@ -39,7 +39,7 @@ class SplCaster
         return self::castSplArray($c, $a, $stub, $isNested);
     }
 
-    public static function castHeap(\Iterator $c, array $a, Stub $stub, $isNested)
+    public static function castHeap(\Iterator $c, array $a, Stub $stub, bool $isNested)
     {
         $a += [
             Caster::PREFIX_VIRTUAL.'heap' => iterator_to_array(clone $c),
@@ -129,7 +129,7 @@ class SplCaster
             }
         }
 
-        if (isset($a[$prefix.'realPath'])) {
+        if ($a[$prefix.'realPath'] ?? false) {
             $a[$prefix.'realPath'] = new LinkStub($a[$prefix.'realPath']);
         }
 
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/AbstractCloner.php b/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/AbstractCloner.php
index 739e0699..ac55da55 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/AbstractCloner.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/AbstractCloner.php
@@ -309,7 +309,7 @@ abstract class AbstractCloner implements ClonerInterface
         $obj = $stub->value;
         $class = $stub->class;
 
-        if (\PHP_VERSION_ID < 80000 ? "\0" === ($class[15] ?? null) : false !== strpos($class, "@anonymous\0")) {
+        if (\PHP_VERSION_ID < 80000 ? "\0" === ($class[15] ?? null) : str_contains($class, "@anonymous\0")) {
             $stub->class = get_debug_type($obj);
         }
         if (isset($this->classInfo[$class])) {
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/Data.php b/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/Data.php
index c695a11a..c8688622 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/Data.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Cloner/Data.php
@@ -155,16 +155,25 @@ class Data implements \ArrayAccess, \Countable, \IteratorAggregate
         return $this->__isset($key);
     }
 
+    /**
+     * @return mixed
+     */
     public function offsetGet($key)
     {
         return $this->__get($key);
     }
 
+    /**
+     * @return void
+     */
     public function offsetSet($key, $value)
     {
         throw new \BadMethodCallException(self::class.' objects are immutable.');
     }
 
+    /**
+     * @return void
+     */
     public function offsetUnset($key)
     {
         throw new \BadMethodCallException(self::class.' objects are immutable.');
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/AbstractDumper.php b/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/AbstractDumper.php
index 941f8c68..6064ea99 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/AbstractDumper.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/AbstractDumper.php
@@ -63,7 +63,7 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
      */
     public function setOutput($output)
     {
-        $prev = null !== $this->outputStream ? $this->outputStream : $this->lineDumper;
+        $prev = $this->outputStream ?? $this->lineDumper;
 
         if (\is_callable($output)) {
             $this->outputStream = null;
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/CliDumper.php b/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/CliDumper.php
index ab919e15..c1539ee0 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/CliDumper.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/CliDumper.php
@@ -150,7 +150,7 @@ class CliDumper extends AbstractDumper
                     case is_nan($value):  $value = 'NAN'; break;
                     default:
                         $value = (string) $value;
-                        if (false === strpos($value, $this->decimalPoint)) {
+                        if (!str_contains($value, $this->decimalPoint)) {
                             $value .= $this->decimalPoint.'0';
                         }
                         break;
@@ -324,7 +324,7 @@ class CliDumper extends AbstractDumper
      * @param bool $hasChild When the dump of the hash has child item
      * @param int  $cut      The number of items the hash has been cut by
      */
-    protected function dumpEllipsis(Cursor $cursor, $hasChild, $cut)
+    protected function dumpEllipsis(Cursor $cursor, bool $hasChild, int $cut)
     {
         if ($cut) {
             $this->line .= ' …';
@@ -428,7 +428,7 @@ class CliDumper extends AbstractDumper
      *
      * @return string The value with style decoration
      */
-    protected function style($style, $value, $attr = [])
+    protected function style(string $style, string $value, array $attr = [])
     {
         if (null === $this->colors) {
             $this->colors = $this->supportsColors();
@@ -441,7 +441,7 @@ class CliDumper extends AbstractDumper
 
         if (isset($attr['ellipsis'], $attr['ellipsis-type'])) {
             $prefix = substr($value, 0, -$attr['ellipsis']);
-            if ('cli' === \PHP_SAPI && 'path' === $attr['ellipsis-type'] && isset($_SERVER[$pwd = '\\' === \DIRECTORY_SEPARATOR ? 'CD' : 'PWD']) && 0 === strpos($prefix, $_SERVER[$pwd])) {
+            if ('cli' === \PHP_SAPI && 'path' === $attr['ellipsis-type'] && isset($_SERVER[$pwd = '\\' === \DIRECTORY_SEPARATOR ? 'CD' : 'PWD']) && str_starts_with($prefix, $_SERVER[$pwd])) {
                 $prefix = '.'.substr($prefix, \strlen($_SERVER[$pwd]));
             }
             if (!empty($attr['ellipsis-tail'])) {
@@ -475,7 +475,7 @@ class CliDumper extends AbstractDumper
             } else {
                 $value = "\033[{$this->styles[$style]}m".$value;
             }
-            if ($cchrCount && $endCchr === substr($value, -\strlen($endCchr))) {
+            if ($cchrCount && str_ends_with($value, $endCchr)) {
                 $value = substr($value, 0, -\strlen($endCchr));
             } else {
                 $value .= "\033[{$this->styles['default']}m";
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php b/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php
index c3cd3221..2e2c8181 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/ContextProvider/SourceContextProvider.php
@@ -56,7 +56,7 @@ final class SourceContextProvider implements ContextProviderInterface
                 $line = $trace[$i]['line'] ?? $line;
 
                 while (++$i < $this->limit) {
-                    if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && 0 !== strpos($trace[$i]['function'], 'call_user_func')) {
+                    if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && !str_starts_with($trace[$i]['function'], 'call_user_func')) {
                         $file = $trace[$i]['file'];
                         $line = $trace[$i]['line'];
 
@@ -98,7 +98,7 @@ final class SourceContextProvider implements ContextProviderInterface
 
         if (null !== $this->projectDir) {
             $context['project_dir'] = $this->projectDir;
-            if (0 === strpos($file, $this->projectDir)) {
+            if (str_starts_with($file, $this->projectDir)) {
                 $context['file_relative'] = ltrim(substr($file, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR);
             }
         }
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/HtmlDumper.php b/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/HtmlDumper.php
index 9bbd2d65..6c3abaa2 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/HtmlDumper.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Dumper/HtmlDumper.php
@@ -116,21 +116,16 @@ class HtmlDumper extends CliDumper
 
     /**
      * Sets an HTML header that will be dumped once in the output stream.
-     *
-     * @param string $header An HTML string
      */
-    public function setDumpHeader($header)
+    public function setDumpHeader(?string $header)
     {
         $this->dumpHeader = $header;
     }
 
     /**
      * Sets an HTML prefix and suffix that will encapse every single dump.
-     *
-     * @param string $prefix The prepended HTML string
-     * @param string $suffix The appended HTML string
      */
-    public function setDumpBoundaries($prefix, $suffix)
+    public function setDumpBoundaries(string $prefix, string $suffix)
     {
         $this->dumpPrefix = $prefix;
         $this->dumpSuffix = $suffix;
@@ -153,7 +148,7 @@ class HtmlDumper extends CliDumper
      */
     protected function getDumpHeader()
     {
-        $this->headerIsDumped = null !== $this->outputStream ? $this->outputStream : $this->lineDumper;
+        $this->headerIsDumped = $this->outputStream ?? $this->lineDumper;
 
         if (null !== $this->dumpHeader) {
             return $this->dumpHeader;
@@ -851,7 +846,7 @@ EOHTML
     /**
      * {@inheritdoc}
      */
-    protected function style($style, $value, $attr = [])
+    protected function style(string $style, string $value, array $attr = [])
     {
         if ('' === $value) {
             return '';
@@ -951,7 +946,7 @@ EOHTML
         if (-1 === $this->lastDepth) {
             $this->line = sprintf($this->dumpPrefix, $this->dumpId, $this->indentPad).$this->line;
         }
-        if ($this->headerIsDumped !== (null !== $this->outputStream ? $this->outputStream : $this->lineDumper)) {
+        if ($this->headerIsDumped !== ($this->outputStream ?? $this->lineDumper)) {
             $this->line = $this->getDumpHeader().$this->line;
         }
 
@@ -985,7 +980,7 @@ EOHTML
     }
 }
 
-function esc($str)
+function esc(string $str)
 {
     return htmlspecialchars($str, \ENT_QUOTES, 'UTF-8');
 }
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Server/Connection.php b/data/web/inc/lib/vendor/symfony/var-dumper/Server/Connection.php
index d8be2358..55d9214d 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Server/Connection.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Server/Connection.php
@@ -31,7 +31,7 @@ class Connection
      */
     public function __construct(string $host, array $contextProviders = [])
     {
-        if (false === strpos($host, '://')) {
+        if (!str_contains($host, '://')) {
             $host = 'tcp://'.$host;
         }
 
@@ -78,7 +78,7 @@ class Connection
         return false;
     }
 
-    private static function nullErrorHandler($t, $m)
+    private static function nullErrorHandler(int $t, string $m)
     {
         // no-op
     }
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/Server/DumpServer.php b/data/web/inc/lib/vendor/symfony/var-dumper/Server/DumpServer.php
index 28decf31..7cb5bf0c 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/Server/DumpServer.php
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/Server/DumpServer.php
@@ -30,7 +30,7 @@ class DumpServer
 
     public function __construct(string $host, LoggerInterface $logger = null)
     {
-        if (false === strpos($host, '://')) {
+        if (!str_contains($host, '://')) {
             $host = 'tcp://'.$host;
         }
 
diff --git a/data/web/inc/lib/vendor/symfony/var-dumper/composer.json b/data/web/inc/lib/vendor/symfony/var-dumper/composer.json
index 16da4888..2d4889d0 100644
--- a/data/web/inc/lib/vendor/symfony/var-dumper/composer.json
+++ b/data/web/inc/lib/vendor/symfony/var-dumper/composer.json
@@ -18,7 +18,7 @@
     "require": {
         "php": ">=7.2.5",
         "symfony/polyfill-mbstring": "~1.0",
-        "symfony/polyfill-php80": "^1.15"
+        "symfony/polyfill-php80": "^1.16"
     },
     "require-dev": {
         "ext-iconv": "*",
diff --git a/data/web/inc/triggers.inc.php b/data/web/inc/triggers.inc.php
index fc8e37b5..a2342dfc 100644
--- a/data/web/inc/triggers.inc.php
+++ b/data/web/inc/triggers.inc.php
@@ -55,7 +55,7 @@ if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) {
 	}
 }
 
-if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['acl']['login_as'] == "1") {
+if (isset($_SESSION['mailcow_cc_role']) && (isset($_SESSION['acl']['login_as']) && $_SESSION['acl']['login_as'] == "1")) {
 	if (isset($_GET["duallogin"])) {
     $duallogin = html_entity_decode(rawurldecode($_GET["duallogin"]));
     if (filter_var($duallogin, FILTER_VALIDATE_EMAIL)) {
diff --git a/data/web/inc/vars.inc.php b/data/web/inc/vars.inc.php
index 426a9dad..d0022694 100644
--- a/data/web/inc/vars.inc.php
+++ b/data/web/inc/vars.inc.php
@@ -45,21 +45,21 @@ $autodiscover_config = array(
   // The autoconfig service will additionally announce the STARTTLS-enabled ports, specified in the "tlsport" variable.
   'imap' => array(
     'server' => $mailcow_hostname,
-    'port' => end(explode(':', getenv('IMAPS_PORT'))),
-    'tlsport' => end(explode(':', getenv('IMAP_PORT'))),
+    'port' => substr(getenv('IMAPS_PORT'), strrpos(getenv('IMAPS_PORT'), ':') + 1),
+    'tlsport' => substr(getenv('POP_PORT'), strrpos(getenv('IMAP_PORT'), ':') + 1)
   ),
   'pop3' => array(
     'server' => $mailcow_hostname,
-    'port' => end(explode(':', getenv('POPS_PORT'))),
-    'tlsport' => end(explode(':', getenv('POP_PORT'))),
+    'port' => substr(getenv('POPS_PORT'), strrpos(getenv('POPS_PORT'), ':') + 1),
+    'tlsport' => substr(getenv('POP_PORT'), strrpos(getenv('POP_PORT'), ':') + 1)
   ),
   'smtp' => array(
     'server' => $mailcow_hostname,
-    'port' => end(explode(':', getenv('SMTPS_PORT'))),
-    'tlsport' => end(explode(':', getenv('SUBMISSION_PORT'))),
+    'port' => substr(getenv('SMTPS_PORT'), strrpos(getenv('SMTPS_PORT'), ':') + 1),
+    'tlsport' => substr(getenv('SUBMISSION_PORT'), strrpos(getenv('SUBMISSION_PORT'), ':') + 1)
   ),
   'activesync' => array(
-    'url' => 'https://'.$mailcow_hostname.($https_port == 443 ? '' : ':'.$https_port).'/Microsoft-Server-ActiveSync',
+    'url' => 'https://' . $mailcow_hostname . ($https_port == 443 ? '' : ':' . $https_port) . '/Microsoft-Server-ActiveSync',
   ),
   'caldav' => array(
     'server' => $mailcow_hostname,
diff --git a/data/web/index.php b/data/web/index.php
index 204b2a4e..47f34279 100644
--- a/data/web/index.php
+++ b/data/web/index.php
@@ -99,7 +99,7 @@ $_SESSION['index_query_string'] = $_SERVER['QUERY_STRING'];
               foreach ($MAILCOW_APPS as $app) {
                 if (getenv('SKIP_SOGO') == "y" && preg_match('/^\/SOGo/i', $app['link'])) { continue; }
               ?>
-                <a href="<?= htmlspecialchars($app['link']); ?>" role="button" title="<?= htmlspecialchars($app['description']); ?>" class="btn btn-primary btn-lg btn-block"><?= htmlspecialchars($app['name']); ?></a>
+                <a href="<?=(isset($app['link'])) ? htmlspecialchars($app['link']) : '';?>" role="button" title="<?=(isset($app['description'])) ? htmlspecialchars($app['description']) : '';?>" class="btn btn-primary btn-lg btn-block"><?= htmlspecialchars($app['name']); ?></a>
               <?php
               }
             }
diff --git a/data/web/modals/admin.php b/data/web/modals/admin.php
index da2a2158..22bb412c 100644
--- a/data/web/modals/admin.php
+++ b/data/web/modals/admin.php
@@ -23,7 +23,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
           <div class="form-group">
             <label class="control-label col-sm-2" for="content"><?=$lang['admin']['rsetting_content'];?>:</label>
             <div class="col-sm-10">
-              <textarea class="form-control" id="adminRspamdSettingsContent" name="content" rows="10"><?=$rsetting_details['content'];?></textarea>
+              <textarea class="form-control" id="adminRspamdSettingsContent" name="content" rows="10"><?=(isset($rsetting_details['content'])) ? $rsetting_details['content'] : '';?></textarea>
             </div>
           </div>
           <div class="form-group">