]> source.dussan.org Git - nextcloud-server.git/commitdiff
Replace custom tooltips with native ones and add description to all elements which... 37244/head
authorjulia.kirschenheuter <julia.kirschenheuter@nextcloud.com>
Wed, 15 Mar 2023 16:57:06 +0000 (17:57 +0100)
committerjulia.kirschenheuter <julia.kirschenheuter@nextcloud.com>
Thu, 16 Mar 2023 11:10:45 +0000 (12:10 +0100)
Signed-off-by: julia.kirschenheuter <julia.kirschenheuter@nextcloud.com>
apps/user_ldap/js/wizard/view.js
apps/user_ldap/templates/part.wizard-groupfilter.php
apps/user_ldap/templates/part.wizard-loginfilter.php
apps/user_ldap/templates/part.wizard-server.php
apps/user_ldap/templates/part.wizard-userfilter.php
apps/user_ldap/templates/renewpassword.php
apps/user_ldap/templates/settings.php

index 8a530c17e4fff108b37351017eeec7fb2af27a5b..5917dbf44c9d09d3c106a56ffd7faf7f0c4155d1 100644 (file)
@@ -356,7 +356,6 @@ OCA = OCA || {};
                        this.$settings.tabs({});
                        $('#ldapSettings button:not(.icon-default-style):not(.ui-multiselect)').button();
                        $('#ldapSettings').tabs({ beforeActivate: this.onTabChange });
-                       $('#ldapSettings :input').tooltip({placement: "right", container: "body", trigger: "hover"});
 
                        this.initControls();
                        this.disableTabs();
index a059b466812abd79e569e9faa27d63ecdc625c44..19c2fed67843b4d673fc2be4a09ff81cdc713cde 100644 (file)
                <p class="ldapManyGroupsSupport hidden">
                        <label></label>
                        <select class="ldapGroupList ldapGroupListAvailable" multiple="multiple"
+                                       aria-describedby="ldapGroupListAvailable_instructions"
                                        title="<?php p($l->t('Available groups'));?>"></select>
+                       <p class="hidden-visually" id="ldapGroupListAvailable_instructions">
+                                       <?php p($l->t('Available groups'));?>
+                       </p>
                        <span class="buttonSpan">
                                <button class="ldapGroupListSelect" type="button">&gt;</button><br/>
                                <button class="ldapGroupListDeselect" type="button">&lt;</button>
                        </span>
                        <select class="ldapGroupList ldapGroupListSelected" multiple="multiple"
+                                       aria-describedby="ldapGroupListSelected_instructions"
                                        title="<?php p($l->t('Selected groups'));?>"></select>
+                       <p class="hidden-visually" id="ldapGroupListSelected_instructions">
+                                       <?php p($l->t('Selected groups'));?>
+                       </p>
                </p>
                <p>
                        <label><a id='toggleRawGroupFilter' class='ldapToggle'>↓ <?php p($l->t('Edit LDAP Query'));?></a></label>
                <p id="rawGroupFilterContainer" class="invisible">
                        <textarea type="text" id="ldap_group_filter" name="ldap_group_filter"
                                          placeholder="<?php p($l->t('Edit LDAP Query'));?>"
+                                         aria-describedby="rawGroupFilterContainer_instructions"
                                          title="<?php p($l->t('The filter specifies which LDAP groups shall have access to the %s instance.', [$theme->getName()]));?>">
                        </textarea>
+                       <p class="hidden-visually" id="rawGroupFilterContainer_instructions">
+                               <?php p($l->t('The filter specifies which LDAP groups shall have access to the %s instance.', [$theme->getName()]));?>
+                       </p>
+
                </p>
                <p>
                        <div class="ldapWizardInfo invisible">&nbsp;</div>
index 1cc46ff52c41fc98832147b64b5c061a1760c7a4..d89d83e95c604b6462a3a3c729d28dbaba1528b1 100644 (file)
@@ -9,8 +9,12 @@
                        </label>
 
                        <input type="checkbox" id="ldap_loginfilter_username"
+                                  aria-describedby="ldap_loginfilter_username_instructions"
                                   title="<?php p($l->t('Allows login against the LDAP/AD username, which is either "uid" or "sAMAccountName" and will be detected.'));?>"
                                   name="ldap_loginfilter_username" value="1" />
+                       <p class="hidden-visually" id="ldap_loginfilter_username_instructions">
+                               <?php p($l->t('Allows login against the LDAP/AD username, which is either "uid" or "sAMAccountName" and will be detected.'));?>
+                       </p>
                </p>
                <p>
                        <label for="ldap_loginfilter_email">
 
                        <input type="checkbox" id="ldap_loginfilter_email"
                                   title="<?php p($l->t('Allows login against an email attribute. "mail" and "mailPrimaryAddress" allowed.'));?>"
+                                  aria-describedby="ldap_loginfilter_email_instructions"
                                   name="ldap_loginfilter_email" value="1" />
+                       <p class="hidden-visually" id="ldap_loginfilter_email_instructions">
+                               <?php p($l->t('Allows login against an email attribute. "mail" and "mailPrimaryAddress" allowed.'));?>
+                       </p>
                </p>
                <p>
                        <label for="ldap_loginfilter_attributes">
                        <textarea type="text" id="ldap_login_filter" name="ldap_login_filter"
                                class="ldapFilterInputElement"
                                placeholder="<?php p($l->t('Edit LDAP Query'));?>"
+                               aria-describedby="ldap_login_filter_instructions"
                                title="<?php p($l->t('Defines the filter to apply, when login is attempted. "%%uid" replaces the username in the login action. Example: "uid=%%uid"'));?>">
                        </textarea>
+               <p class="hidden-visually" id="ldap_login_filter_instructions">
+                       <?php p($l->t('Defines the filter to apply, when login is attempted. "%%uid" replaces the username in the login action. Example: "uid=%%uid"'));?>
+               </p>
                </p>
                <p>
                        <div class="ldapWizardInfo invisible">&nbsp;</div>
                        <input type="text" id="ldap_test_loginname" name="ldap_test_loginname"
                                   placeholder="<?php p($l->t('Test Loginname'));?>"
                                   class="ldapVerifyInput"
-                                  title="Attempts to receive a DN for the given loginname and the current login filter"/>
+                                  aria-describedby="ldap_test_loginname_instructions"
+                                  title="<?php p($l->t('Attempts to receive a DN for the given loginname and the current login filter'));?>"/>
+                       <p class="hidden-visually" id="ldap_test_loginname_instructions">
+                               <?php p($l->t('Attempts to receive a DN for the given loginname and the current login filter'));?>
+                       </p>
                        <button class="ldapVerifyLoginName" name="ldapTestLoginSettings" type="button" disabled="disabled">
                                <?php p($l->t('Verify settings'));?>
                        </button>
index ff8630c62cd174dd167d52729e6da6ffef752216..afc8f55f94cfd89c3e9a7a90298b028f1602a4c0 100644 (file)
                ?>
                </select>
                <button type="button" id="ldap_action_add_configuration"
+                       aria-describedby="ldap_action_add_configuration_instructions"
                        name="ldap_action_add_configuration" class="icon-add icon-default-style"
                        title="<?php p($l->t('Add a new configuration'));?>">&nbsp;</button>
+               <p class="hidden-visually" id="ldap_action_add_configuration_instructions">
+                       <?php p($l->t('Add a new configuration'));?>
+               </p>
                <button type="button" id="ldap_action_copy_configuration"
                        name="ldap_action_copy_configuration"
+                       aria-describedby="ldap_action_copy_configuration_instructions"
                        class="ldapIconCopy icon-default-style"
                        title="<?php p($l->t('Copy current configuration into new directory binding'));?>">&nbsp;</button>
+               <p class="hidden-visually" id="ldap_action_copy_configuration_instructions">
+                       <?php p($l->t('Copy current configuration into new directory binding'));?>
+               </p>
                <button type="button" id="ldap_action_delete_configuration"
+                       aria-describedby="ldap_action_delete_configuration_instructions"
                        name="ldap_action_delete_configuration" class="icon-delete icon-default-style"
                        title="<?php p($l->t('Delete the current configuration'));?>">&nbsp;</button>
+               <p class="hidden-visually" id="ldap_action_delete_configuration_instructions">
+                       <?php p($l->t('Delete the current configuration'));?>
+               </p>
                </p>
 
                <div class="hostPortCombinator">
                                        <div class="table">
                                                <input type="text" class="host" id="ldap_host"
                                                        name="ldap_host"
+                                                       aria-describedby="ldap_host_instructions"
                                                        placeholder="<?php p($l->t('Host'));?>"
                                                        title="<?php p($l->t('You can omit the protocol, unless you require SSL. If so, start with ldaps://'));?>"
                                                        />
+                                               <p class="hidden-visually" id="ldap_host_instructions">
+                                                       <?php p($l->t('You can omit the protocol, unless you require SSL. If so, start with ldaps://'));?>
+                                               </p>
                                                <span class="hostPortCombinatorSpan">
                                                        <input type="number" id="ldap_port" name="ldap_port"
                                                                placeholder="<?php p($l->t('Port'));?>" />
                        <div class="tablerow">
                                <input type="text" id="ldap_dn" name="ldap_dn"
                                class="tablecell"
+                               aria-describedby="ldap_dn_instructions"
                                placeholder="<?php p($l->t('User DN'));?>" autocomplete="off"
                                title="<?php p($l->t('The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty.'));?>"
                                />
+                               <p class="hidden-visually" id="ldap_dn_instructions">
+                                       <?php p($l->t('The DN of the client user with which the bind shall be done, e.g. uid=agent,dc=example,dc=com. For anonymous access, leave DN and Password empty.'));?>
+                               </p>
                        </div>
 
                        <div class="tablerow">
                                <input type="password" id="ldap_agent_password"
                                class="tablecell" name="ldap_agent_password"
+                               aria-describedby="ldap_agent_password_instructions"
                                placeholder="<?php p($l->t('Password'));?>" autocomplete="off"
                                title="<?php p($l->t('For anonymous access, leave DN and Password empty.'));?>"
                                />
+                               <p class="hidden-visually" id="ldap_agent_password_instructions">
+                                       <?php p($l->t('For anonymous access, leave DN and Password empty.'));?>
+                               </p>
                                <button class="ldapSaveAgentCredentials" name="ldapSaveAgentCredentials" type="button">
                                        <?php p($l->t('Save Credentials'));?>
                                </button>
                        <div class="tablerow">
                                <textarea id="ldap_base" name="ldap_base"
                                        class="tablecell"
+                                       aria-describedby="ldap_base_instructions"
                                        placeholder="<?php p($l->t('One Base DN per line'));?>"
                                        title="<?php p($l->t('You can specify Base DN for users and groups in the Advanced tab'));?>">
                                </textarea>
+                               <p class="hidden-visually" id="ldap_base_instructions">
+                                       <?php p($l->t('You can specify Base DN for users and groups in the Advanced tab'));?>
+                               </p>
                                <button class="ldapDetectBase" name="ldapDetectBase" type="button">
                                        <?php p($l->t('Detect Base DN'));?>
                                </button>
                        <div class="tablerow left">
                                <input type="checkbox" id="ldap_experienced_admin" value="1"
                                        name="ldap_experienced_admin" class="tablecell"
+                                       aria-describedby="ldap_experienced_admin_instructions"
                                        title="<?php p($l->t('Avoids automatic LDAP requests. Better for bigger setups, but requires some LDAP knowledge.'));?>"
                                        />
+                               <p class="hidden-visually" id="ldap_experienced_admin_instructions">
+                                       <?php p($l->t('Avoids automatic LDAP requests. Better for bigger setups, but requires some LDAP knowledge.'));?>
+                               </p>
                                <label for="ldap_experienced_admin" class="tablecell">
                                        <?php p($l->t('Manually enter LDAP filters (recommended for large directories)'));?>
                                </label>
index 2b8c3adb6861c3c8643c14b8ae0c266472e5c977..59ce8a6221d7a9fcaeaab8f5a6f1e988511ca887 100644 (file)
                <p class="ldapManyGroupsSupport hidden">
                        <label></label>
                        <select class="ldapGroupList ldapGroupListAvailable" multiple="multiple"
+                                       aria-describedby="ldapGroupListAvailable_instructions"
                                        title="<?php p($l->t('Available groups'));?>"></select>
+                       <p class="hidden-visually" id="ldapGroupListAvailable_instructions">
+                               <?php p($l->t('Available groups'));?>
+                       </p>
                        <span class="buttonSpan">
                                <button class="ldapGroupListSelect" type="button">&gt;</button><br/>
                                <button class="ldapGroupListDeselect" type="button">&lt;</button>
                        </span>
                        <select class="ldapGroupList ldapGroupListSelected" multiple="multiple"
+                                       aria-describedby="ldapGroupListSelected_instructions"
                                        title="<?php p($l->t('Selected groups'));?>"></select>
+                       <p class="hidden-visually" id="ldapGroupListSelected_instructions">
+                               <?php p($l->t('Selected groups'));?>
+                       </p>
                </p>
                <p>
                        <label><a id='toggleRawUserFilter' class='ldapToggle'>↓ <?php p($l->t('Edit LDAP Query'));?></a></label>
                        <textarea type="text" id="ldap_userlist_filter" name="ldap_userlist_filter"
                                class="ldapFilterInputElement"
                                placeholder="<?php p($l->t('Edit LDAP Query'));?>"
+                               aria-describedby="ldap_userlist_filter_instructions"
                                title="<?php p($l->t('The filter specifies which LDAP users shall have access to the %s instance.', [$theme->getName()]));?>">
                        </textarea>
+               <p class="hidden-visually" id="ldap_userlist_filter_instructions">
+                       <?php p($l->t('The filter specifies which LDAP users shall have access to the %s instance.', [$theme->getName()]));?>
+               </p>
                </p>
                <p>
                        <div class="ldapWizardInfo invisible">&nbsp;</div>
index 752327ce872566b71821c60a28cfe877ec1cc41a..51cf898e1339b91d0484d2e455e64a029525a26b 100644 (file)
@@ -41,8 +41,8 @@ style('user_ldap', 'renewPassword');
                                placeholder="<?php echo $l->t('New password');?>"
                                data-typetoggle="#personal-show" autofocus autocomplete="off" autocapitalize="off" autocorrect="off" required/>
                </p>
-               
-               <input type="submit" id="submit" class="login primary icon-confirm-white" title="" value="<?php p($l->t('Renew password')); ?>"/>
+
+               <input type="submit" id="submit" class="login primary icon-confirm-white" value="<?php p($l->t('Renew password')); ?>"/>
 
                <?php if (!empty($_['invalidpassword'])) { ?>
                        <p class="warning">
index 3e11b89a7c4141fc6780245a51ef6a80553719e1..a28ef55a3069725691199cf2625a35b4df57abac 100644 (file)
@@ -78,22 +78,22 @@ style('user_ldap', 'settings');
                <div id="ldapAdvancedAccordion">
                        <h3><?php p($l->t('Connection Settings'));?></h3>
                        <div>
-                               <p><label for="ldap_configuration_active"><?php p($l->t('Configuration Active'));?></label><input type="checkbox" id="ldap_configuration_active" name="ldap_configuration_active" value="1" data-default="<?php p($_['ldap_configuration_active_default']); ?>"  title="<?php p($l->t('When unchecked, this configuration will be skipped.'));?>" /></p>
-                               <p><label for="ldap_backup_host"><?php p($l->t('Backup (Replica) Host'));?></label><input type="text" id="ldap_backup_host" name="ldap_backup_host" data-default="<?php p($_['ldap_backup_host_default']); ?>" title="<?php p($l->t('Give an optional backup host. It must be a replica of the main LDAP/AD server.'));?>"></p>
+                               <p><label for="ldap_configuration_active"><?php p($l->t('Configuration Active'));?></label><input type="checkbox" id="ldap_configuration_active" name="ldap_configuration_active" value="1" data-default="<?php p($_['ldap_configuration_active_default']); ?>" aria-describedby="ldap_configuration_active_instructions" title="<?php p($l->t('When unchecked, this configuration will be skipped.'));?>" /><p class="hidden-visually" id="ldap_configuration_active_instructions"><?php p($l->t('When unchecked, this configuration will be skipped.'));?></p></p>
+                               <p><label for="ldap_backup_host"><?php p($l->t('Backup (Replica) Host'));?></label><input type="text" id="ldap_backup_host" name="ldap_backup_host" data-default="<?php p($_['ldap_backup_host_default']); ?>" aria-describedby="ldap_backup_host_instructions" title="<?php p($l->t('Give an optional backup host. It must be a replica of the main LDAP/AD server.'));?>"><p class="hidden-visually" id="ldap_backup_host_instructions"><?php p($l->t('Give an optional backup host. It must be a replica of the main LDAP/AD server.'));?></p></p>
                                <p><label for="ldap_backup_port"><?php p($l->t('Backup (Replica) Port'));?></label><input type="number" id="ldap_backup_port" name="ldap_backup_port" data-default="<?php p($_['ldap_backup_port_default']); ?>"  /></p>
-                               <p><label for="ldap_override_main_server"><?php p($l->t('Disable Main Server'));?></label><input type="checkbox" id="ldap_override_main_server" name="ldap_override_main_server" value="1" data-default="<?php p($_['ldap_override_main_server_default']); ?>"  title="<?php p($l->t('Only connect to the replica server.'));?>" /></p>
-                               <p><label for="ldap_turn_off_cert_check"><?php p($l->t('Turn off SSL certificate validation.'));?></label><input type="checkbox" id="ldap_turn_off_cert_check" name="ldap_turn_off_cert_check" title="<?php p($l->t('Not recommended, use it for testing only! If connection only works with this option, import the LDAP server\'s SSL certificate in your %s server.', [$theme->getName()]));?>" data-default="<?php p($_['ldap_turn_off_cert_check_default']); ?>" value="1"><br/></p>
-                               <p><label for="ldap_cache_ttl"><?php p($l->t('Cache Time-To-Live'));?></label><input type="number" id="ldap_cache_ttl" name="ldap_cache_ttl" title="<?php p($l->t('in seconds. A change empties the cache.'));?>" data-default="<?php p($_['ldap_cache_ttl_default']); ?>" /></p>
+                               <p><label for="ldap_override_main_server"><?php p($l->t('Disable Main Server'));?></label><input type="checkbox" id="ldap_override_main_server" name="ldap_override_main_server" value="1" data-default="<?php p($_['ldap_override_main_server_default']); ?>" aria-describedby="ldap_override_main_server_instructions" title="<?php p($l->t('Only connect to the replica server.'));?>" /><p class="hidden-visually" id="ldap_override_main_server_instructions"><?php p($l->t('Only connect to the replica server.'));?></p></p>
+                               <p><label for="ldap_turn_off_cert_check"><?php p($l->t('Turn off SSL certificate validation.'));?></label><input type="checkbox" id="ldap_turn_off_cert_check" name="ldap_turn_off_cert_check" aria-describedby="ldap_turn_off_cert_check_instructions" title="<?php p($l->t('Not recommended, use it for testing only! If connection only works with this option, import the LDAP server\'s SSL certificate in your %s server.', [$theme->getName()]));?>" data-default="<?php p($_['ldap_turn_off_cert_check_default']); ?>" value="1"><p class="hidden-visually" id="ldap_turn_off_cert_check_instructions"><?php p($l->t('Not recommended, use it for testing only! If connection only works with this option, import the LDAP server\'s SSL certificate in your %s server.', [$theme->getName()]));?></p><br/></p>
+                               <p><label for="ldap_cache_ttl"><?php p($l->t('Cache Time-To-Live'));?></label><input type="number" id="ldap_cache_ttl" name="ldap_cache_ttl" aria-describedby="ldap_cache_ttl_instructions" title="<?php p($l->t('in seconds. A change empties the cache.'));?>" data-default="<?php p($_['ldap_cache_ttl_default']); ?>" /><p class="hidden-visually" id="ldap_cache_ttl_instructions"><?php p($l->t('in seconds. A change empties the cache.'));?></p></p>
                        </div>
                        <h3><?php p($l->t('Directory Settings'));?></h3>
                        <div>
-                               <p><label for="ldap_display_name"><?php p($l->t('User Display Name Field'));?></label><input type="text" id="ldap_display_name" name="ldap_display_name" data-default="<?php p($_['ldap_display_name_default']); ?>" title="<?php p($l->t('The LDAP attribute to use to generate the user\'s display name.'));?>" /></p>
-                               <p><label for="ldap_user_display_name_2"><?php p($l->t('2nd User Display Name Field'));?></label><input type="text" id="ldap_user_display_name_2" name="ldap_user_display_name_2" data-default="<?php p($_['ldap_user_display_name_2_default']); ?>" title="<?php p($l->t('Optional. An LDAP attribute to be added to the display name in brackets. Results in e.g. »John Doe (john.doe@example.org)«.'));?>" /></p>
-                               <p><label for="ldap_base_users"><?php p($l->t('Base User Tree'));?></label><textarea id="ldap_base_users" name="ldap_base_users" placeholder="<?php p($l->t('One User Base DN per line'));?>" data-default="<?php p($_['ldap_base_users_default']); ?>" title="<?php p($l->t('Base User Tree'));?>"></textarea></p>
-                               <p><label for="ldap_attributes_for_user_search"><?php p($l->t('User Search Attributes'));?></label><textarea id="ldap_attributes_for_user_search" name="ldap_attributes_for_user_search" placeholder="<?php p($l->t('Optional; one attribute per line'));?>" data-default="<?php p($_['ldap_attributes_for_user_search_default']); ?>" title="<?php p($l->t('User Search Attributes'));?>"></textarea></p>
-                               <p><label for="ldap_group_display_name"><?php p($l->t('Group Display Name Field'));?></label><input type="text" id="ldap_group_display_name" name="ldap_group_display_name" data-default="<?php p($_['ldap_group_display_name_default']); ?>" title="<?php p($l->t('The LDAP attribute to use to generate the groups\'s display name.'));?>" /></p>
-                               <p><label for="ldap_base_groups"><?php p($l->t('Base Group Tree'));?></label><textarea id="ldap_base_groups" name="ldap_base_groups" placeholder="<?php p($l->t('One Group Base DN per line'));?>" data-default="<?php p($_['ldap_base_groups_default']); ?>" title="<?php p($l->t('Base Group Tree'));?>"></textarea></p>
-                               <p><label for="ldap_attributes_for_group_search"><?php p($l->t('Group Search Attributes'));?></label><textarea id="ldap_attributes_for_group_search" name="ldap_attributes_for_group_search" placeholder="<?php p($l->t('Optional; one attribute per line'));?>" data-default="<?php p($_['ldap_attributes_for_group_search_default']); ?>" title="<?php p($l->t('Group Search Attributes'));?>"></textarea></p>
+                               <p><label for="ldap_display_name"><?php p($l->t('User Display Name Field'));?></label><input type="text" id="ldap_display_name" name="ldap_display_name" data-default="<?php p($_['ldap_display_name_default']); ?>" aria-describedby="ldap_display_name_instructions" title="<?php p($l->t('The LDAP attribute to use to generate the user\'s display name.'));?>" /><p class="hidden-visually" id="ldap_display_name_instructions"><?php p($l->t('The LDAP attribute to use to generate the user\'s display name.'));?></p></p>
+                               <p><label for="ldap_user_display_name_2"><?php p($l->t('2nd User Display Name Field'));?></label><input type="text" id="ldap_user_display_name_2" name="ldap_user_display_name_2" data-default="<?php p($_['ldap_user_display_name_2_default']); ?>" aria-describedby="ldap_user_display_name_2_instructions" title="<?php p($l->t('Optional. An LDAP attribute to be added to the display name in brackets. Results in e.g. »John Doe (john.doe@example.org)«.'));?>" /><p class="hidden-visually" id="ldap_user_display_name_2_instructions"><?php p($l->t('Optional. An LDAP attribute to be added to the display name in brackets. Results in e.g. »John Doe (john.doe@example.org)«.'));?></p></p>
+                               <p><label for="ldap_base_users"><?php p($l->t('Base User Tree'));?></label><textarea id="ldap_base_users" name="ldap_base_users" placeholder="<?php p($l->t('One User Base DN per line'));?>" data-default="<?php p($_['ldap_base_users_default']); ?>" aria-describedby="ldap_base_users_instructions" title="<?php p($l->t('Base User Tree'));?>"></textarea><p class="hidden-visually" id="ldap_base_users_instructions"><?php p($l->t('Base User Tree'));?></p></p>
+                               <p><label for="ldap_attributes_for_user_search"><?php p($l->t('User Search Attributes'));?></label><textarea id="ldap_attributes_for_user_search" name="ldap_attributes_for_user_search" placeholder="<?php p($l->t('Optional; one attribute per line'));?>" data-default="<?php p($_['ldap_attributes_for_user_search_default']); ?>" aria-describedby="ldap_attributes_for_user_search_instructions" title="<?php p($l->t('User Search Attributes'));?>"></textarea><p class="hidden-visually" id="ldap_attributes_for_user_search_instructions"><?php p($l->t('User Search Attributes'));?></p></p>
+                               <p><label for="ldap_group_display_name"><?php p($l->t('Group Display Name Field'));?></label><input type="text" id="ldap_group_display_name" name="ldap_group_display_name" data-default="<?php p($_['ldap_group_display_name_default']); ?>" aria-describedby="ldap_group_display_name_instructions" title="<?php p($l->t('The LDAP attribute to use to generate the groups\'s display name.'));?>" /><p class="hidden-visually" id="ldap_group_display_name_instructions"><?php p($l->t('The LDAP attribute to use to generate the groups\'s display name.'));?></p></p>
+                               <p><label for="ldap_base_groups"><?php p($l->t('Base Group Tree'));?></label><textarea id="ldap_base_groups" name="ldap_base_groups" placeholder="<?php p($l->t('One Group Base DN per line'));?>" data-default="<?php p($_['ldap_base_groups_default']); ?>" aria-describedby="ldap_base_groups_instructions" title="<?php p($l->t('Base Group Tree'));?>"></textarea><p class="hidden-visually" id="ldap_base_groups_instructions"><?php p($l->t('Base Group Tree'));?></p></p>
+                               <p><label for="ldap_attributes_for_group_search"><?php p($l->t('Group Search Attributes'));?></label><textarea id="ldap_attributes_for_group_search" name="ldap_attributes_for_group_search" placeholder="<?php p($l->t('Optional; one attribute per line'));?>" data-default="<?php p($_['ldap_attributes_for_group_search_default']); ?>" aria-describedby="ldap_attributes_for_group_search_instructions" title="<?php p($l->t('Group Search Attributes'));?>"></textarea><p class="hidden-visually" id="ldap_attributes_for_group_search_instructions"><?php p($l->t('Group Search Attributes'));?></p></p>
                                <p><label for="ldap_group_member_assoc_attribute"><?php p($l->t('Group-Member association'));?></label><select id="ldap_group_member_assoc_attribute" name="ldap_group_member_assoc_attribute" data-default="<?php p($_['ldap_group_member_assoc_attribute_default']); ?>" ><option value="uniqueMember"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'uniqueMember')) {
                p(' selected');
        } ?>>uniqueMember</option><option value="memberUid"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'memberUid')) {
@@ -105,20 +105,20 @@ style('user_ldap', 'settings');
        } ?>>gidNumber</option><option value="zimbraMailForwardingAddress"<?php if (isset($_['ldap_group_member_assoc_attribute']) && ($_['ldap_group_member_assoc_attribute'] === 'zimbraMailForwardingAddress')) {
                p(' selected');
        } ?>>zimbraMailForwardingAddress</option></select></p>
-                               <p><label for="ldap_dynamic_group_member_url"><?php p($l->t('Dynamic Group Member URL'));?></label><input type="text" id="ldap_dynamic_group_member_url" name="ldap_dynamic_group_member_url" title="<?php p($l->t('The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)'));?>" data-default="<?php p($_['ldap_dynamic_group_member_url_default']); ?>" /></p>
-                               <p><label for="ldap_nested_groups"><?php p($l->t('Nested Groups'));?></label><input type="checkbox" id="ldap_nested_groups" name="ldap_nested_groups" value="1" data-default="<?php p($_['ldap_nested_groups_default']); ?>"  title="<?php p($l->t('When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)'));?>" /></p>
-                               <p><label for="ldap_paging_size"><?php p($l->t('Paging chunksize'));?></label><input type="number" id="ldap_paging_size" name="ldap_paging_size" title="<?php p($l->t('Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)'));?>" data-default="<?php p($_['ldap_paging_size_default']); ?>" /></p>
-                               <p><label for="ldap_turn_on_pwd_change"><?php p($l->t('Enable LDAP password changes per user'));?></label><span class="inlinetable"><span class="tablerow left"><input type="checkbox" id="ldap_turn_on_pwd_change" name="ldap_turn_on_pwd_change" value="1" data-default="<?php p($_['ldap_turn_on_pwd_change_default']); ?>" title="<?php p($l->t('Allow LDAP users to change their password and allow Super Administrators and Group Administrators to change the password of their LDAP users. Only works when access control policies are configured accordingly on the LDAP server. As passwords are sent in plaintext to the LDAP server, transport encryption must be used and password hashing should be configured on the LDAP server.'));?>" /><span class="tablecell"><?php p($l->t('(New password is sent as plain text to LDAP)'));?></span></span>
+                               <p><label for="ldap_dynamic_group_member_url"><?php p($l->t('Dynamic Group Member URL'));?></label><input type="text" id="ldap_dynamic_group_member_url" name="ldap_dynamic_group_member_url" aria-describedby="ldap_dynamic_group_member_url_instructions" title="<?php p($l->t('The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)'));?>" data-default="<?php p($_['ldap_dynamic_group_member_url_default']); ?>" /><p class="hidden-visually" id="ldap_dynamic_group_member_url_instructions"><?php p($l->t('The LDAP attribute that on group objects contains an LDAP search URL that determines what objects belong to the group. (An empty setting disables dynamic group membership functionality.)'));?></p></p>
+                               <p><label for="ldap_nested_groups"><?php p($l->t('Nested Groups'));?></label><input type="checkbox" id="ldap_nested_groups" name="ldap_nested_groups" value="1" data-default="<?php p($_['ldap_nested_groups_default']); ?>" aria-describedby="ldap_nested_groups_instructions" title="<?php p($l->t('When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)'));?>" /><p class="hidden-visually" id="ldap_nested_groups_instructions"><?php p($l->t('When switched on, groups that contain groups are supported. (Only works if the group member attribute contains DNs.)'));?></p></p>
+                               <p><label for="ldap_paging_size"><?php p($l->t('Paging chunksize'));?></label><input type="number" id="ldap_paging_size" name="ldap_paging_size" aria-describedby="ldap_paging_size_instructions" title="<?php p($l->t('Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)'));?>" data-default="<?php p($_['ldap_paging_size_default']); ?>" /><p class="hidden-visually" id="ldap_paging_size_instructions"><?php p($l->t('Chunksize used for paged LDAP searches that may return bulky results like user or group enumeration. (Setting it 0 disables paged LDAP searches in those situations.)'));?></p></p>
+                               <p><label for="ldap_turn_on_pwd_change"><?php p($l->t('Enable LDAP password changes per user'));?></label><span class="inlinetable"><span class="tablerow left"><input type="checkbox" id="ldap_turn_on_pwd_change" name="ldap_turn_on_pwd_change" value="1" data-default="<?php p($_['ldap_turn_on_pwd_change_default']); ?>" aria-describedby="ldap_turn_on_pwd_change_instructions" title="<?php p($l->t('Allow LDAP users to change their password and allow Super Administrators and Group Administrators to change the password of their LDAP users. Only works when access control policies are configured accordingly on the LDAP server. As passwords are sent in plaintext to the LDAP server, transport encryption must be used and password hashing should be configured on the LDAP server.'));?>" /><p class="hidden-visually" id="ldap_turn_on_pwd_change_instructions"><?php p($l->t('Allow LDAP users to change their password and allow Super Administrators and Group Administrators to change the password of their LDAP users. Only works when access control policies are configured accordingly on the LDAP server. As passwords are sent in plaintext to the LDAP server, transport encryption must be used and password hashing should be configured on the LDAP server.'));?></p><span class="tablecell"><?php p($l->t('(New password is sent as plain text to LDAP)'));?></span></span>
                        </span><br/></p>
-                               <p><label for="ldap_default_ppolicy_dn"><?php p($l->t('Default password policy DN'));?></label><input type="text" id="ldap_default_ppolicy_dn" name="ldap_default_ppolicy_dn" title="<?php p($l->t('The DN of a default password policy that will be used for password expiry handling. Works only when LDAP password changes per user are enabled and is only supported by OpenLDAP. Leave empty to disable password expiry handling.'));?>" data-default="<?php p($_['ldap_default_ppolicy_dn_default']); ?>" /></p>
+                               <p><label for="ldap_default_ppolicy_dn"><?php p($l->t('Default password policy DN'));?></label><input type="text" id="ldap_default_ppolicy_dn" name="ldap_default_ppolicy_dn" aria-describedby="ldap_default_ppolicy_dn_instructions" title="<?php p($l->t('The DN of a default password policy that will be used for password expiry handling. Works only when LDAP password changes per user are enabled and is only supported by OpenLDAP. Leave empty to disable password expiry handling.'));?>" data-default="<?php p($_['ldap_default_ppolicy_dn_default']); ?>" /><p class="hidden-visually" id="ldap_default_ppolicy_dn_instructions"><?php p($l->t('The DN of a default password policy that will be used for password expiry handling. Works only when LDAP password changes per user are enabled and is only supported by OpenLDAP. Leave empty to disable password expiry handling.'));?></p></p>
                        </div>
                        <h3><?php p($l->t('Special Attributes'));?></h3>
                        <div>
-                               <p><label for="ldap_quota_attr"><?php p($l->t('Quota Field'));?></label><input type="text" id="ldap_quota_attr" name="ldap_quota_attr" data-default="<?php p($_['ldap_quota_attr_default']); ?>" title="<?php p($l->t('Leave empty for user\'s default quota. Otherwise, specify an LDAP/AD attribute.'));?>" /></p>
-                               <p><label for="ldap_quota_def"><?php p($l->t('Quota Default'));?></label><input type="text" id="ldap_quota_def" name="ldap_quota_def" data-default="<?php p($_['ldap_quota_def_default']); ?>" title="<?php p($l->t('Override default quota for LDAP users who do not have a quota set in the Quota Field.'));?>" /></p>
-                               <p><label for="ldap_email_attr"><?php p($l->t('Email Field'));?></label><input type="text" id="ldap_email_attr" name="ldap_email_attr" data-default="<?php p($_['ldap_email_attr_default']); ?>" title="<?php p($l->t('Set the user\'s email from their LDAP attribute. Leave it empty for default behaviour.'));?>" /></p>
-                               <p><label for="home_folder_naming_rule"><?php p($l->t('User Home Folder Naming Rule'));?></label><input type="text" id="home_folder_naming_rule" name="home_folder_naming_rule" title="<?php p($l->t('Leave empty for username (default). Otherwise, specify an LDAP/AD attribute.'));?>" data-default="<?php p($_['home_folder_naming_rule_default']); ?>" /></p>
-                               <p><label for="ldap_ext_storage_home_attribute"> <?php p($l->t('"$home" Placeholder Field')); ?></label><input type="text" id="ldap_ext_storage_home_attribute" name="ldap_ext_storage_home_attribute" title="<?php p($l->t('$home in an external storage configuration will be replaced with the value of the specified attribute')); ?>" data-default="<?php p($_['ldap_ext_storage_home_attribute_default']); ?>"></p>
+                               <p><label for="ldap_quota_attr"><?php p($l->t('Quota Field'));?></label><input type="text" id="ldap_quota_attr" name="ldap_quota_attr" data-default="<?php p($_['ldap_quota_attr_default']); ?>" aria-describedby="ldap_quota_attr_instructions" title="<?php p($l->t('Leave empty for user\'s default quota. Otherwise, specify an LDAP/AD attribute.'));?>" /><p class="hidden-visually" id="ldap_quota_attr_instructions"><?php p($l->t('Leave empty for user\'s default quota. Otherwise, specify an LDAP/AD attribute.'));?></p></p>
+                               <p><label for="ldap_quota_def"><?php p($l->t('Quota Default'));?></label><input type="text" id="ldap_quota_def" name="ldap_quota_def" data-default="<?php p($_['ldap_quota_def_default']); ?>" aria-describedby="ldap_quota_def_instructions" title="<?php p($l->t('Override default quota for LDAP users who do not have a quota set in the Quota Field.'));?>" /><p class="hidden-visually" id="ldap_quota_def_instructions"><?php p($l->t('Override default quota for LDAP users who do not have a quota set in the Quota Field.'));?></p></p>
+                               <p><label for="ldap_email_attr"><?php p($l->t('Email Field'));?></label><input type="text" id="ldap_email_attr" name="ldap_email_attr" data-default="<?php p($_['ldap_email_attr_default']); ?>" aria-describedby="ldap_email_attr_instructions" title="<?php p($l->t('Set the user\'s email from their LDAP attribute. Leave it empty for default behaviour.'));?>" /><p class="hidden-visually" id="ldap_email_attr_instructions"><?php p($l->t('Set the user\'s email from their LDAP attribute. Leave it empty for default behaviour.'));?></p></p>
+                               <p><label for="home_folder_naming_rule"><?php p($l->t('User Home Folder Naming Rule'));?></label><input type="text" id="home_folder_naming_rule" name="home_folder_naming_rule" aria-describedby="home_folder_naming_rule_instructions" title="<?php p($l->t('Leave empty for username (default). Otherwise, specify an LDAP/AD attribute.'));?>" data-default="<?php p($_['home_folder_naming_rule_default']); ?>" /><p class="hidden-visually" id="home_folder_naming_rule_instructions"><?php p($l->t('Leave empty for username (default). Otherwise, specify an LDAP/AD attribute.'));?></p></p>
+                               <p><label for="ldap_ext_storage_home_attribute"> <?php p($l->t('"$home" Placeholder Field')); ?></label><input type="text" id="ldap_ext_storage_home_attribute" name="ldap_ext_storage_home_attribute" aria-describedby="ldap_ext_storage_home_attribute_instructions" title="<?php p($l->t('$home in an external storage configuration will be replaced with the value of the specified attribute')); ?>" data-default="<?php p($_['ldap_ext_storage_home_attribute_default']); ?>"><p class="hidden-visually" id="ldap_ext_storage_home_attribute_instructions"><?php p($l->t('$home in an external storage configuration will be replaced with the value of the specified attribute')); ?></p></p>
                        </div>
                </div>
                <?php print_unescaped($_['settingControls']); ?>