Adds API to enable commands to be hidden from help and tab (#1301)

Implements #1300.

Adds CompositeCommand#setHidden(boolean).
This commit is contained in:
tastybento 2020-04-23 11:54:45 -07:00 committed by GitHub
parent eee8709636
commit b1dcec2160
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 230 additions and 1 deletions

View File

@ -53,6 +53,12 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
*/
private boolean configurableRankCommand = false;
/**
* True if command is hidden from help and tab complete
* @since 1.13.0
*/
private boolean hidden = false;
/**
* The parameters string for this command. It is the commands followed by a locale reference.
*/
@ -616,7 +622,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
}
/**
* Returns a list containing all the labels of the subcommands for the provided CompositeCommand.
* Returns a list containing all the labels of the subcommands for the provided CompositeCommand excluding any hidden commands
* @param sender the CommandSender
* @param command the CompositeCommand to get the subcommands from
* @return a list of subcommands labels or an empty list.
@ -624,6 +630,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
@NonNull
private List<String> getSubCommandLabels(@NonNull CommandSender sender, @NonNull CompositeCommand command) {
return command.getSubCommands().values().stream()
.filter(cmd -> !cmd.isHidden())
.filter(cmd -> !cmd.isOnlyPlayer() || sender.isOp() || (sender instanceof Player && cmd.getPermission() != null && (cmd.getPermission().isEmpty() || sender.hasPermission(cmd.getPermission()))) )
.map(CompositeCommand::getLabel).collect(Collectors.toList());
}
@ -775,4 +782,22 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
this.configurableRankCommand = true;
}
/**
* Checks if a command is hidden
* @return the hidden
* @since 1.13.0
*/
public boolean isHidden() {
return hidden;
}
/**
* Sets a command and all its help and tab complete as hidden
* @param hidden whether command is hidden or not
* @since 1.13.0
*/
public void setHidden(boolean hidden) {
this.hidden = hidden;
}
}

View File

@ -39,6 +39,9 @@ public class DefaultHelpCommand extends CompositeCommand {
@Override
public boolean execute(User user, String label, List<String> args) {
// If command is hidden, do not show anything
if (parent.isHidden()) return true;
// Show default help
int depth = 0;
if (args.size() == 1) {
if (NumberUtils.isDigits(args.get(0))) {

View File

@ -0,0 +1,201 @@
package world.bentobox.bentobox.api.commands;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.List;
import org.bukkit.command.CommandSender;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.stubbing.Answer;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.events.command.CommandEvent;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.managers.CommandsManager;
/**
* @author tastybento
*
*/
@RunWith(PowerMockRunner.class)
@PrepareForTest({BentoBox.class, CommandEvent.class})
public class HiddenCommandTest {
@Mock
private BentoBox plugin;
@Mock
private User user;
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
// Set up plugin
Whitebox.setInternalState(BentoBox.class, "instance", plugin);
// Command manager
CommandsManager cm = mock(CommandsManager.class);
when(plugin.getCommandsManager()).thenReturn(cm);
// Translation
when(user.getTranslation(anyString())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, String.class));
}
@After
public void tearDown() {
Mockito.framework().clearInlineMocks();
}
/**
* Test method for {@link world.bentobox.bentobox.api.commands.CompositeCommand#tabComplete(org.bukkit.command.CommandSender, java.lang.String, java.lang.String[])}.
*/
@Test
public void testTabCompleteCommandSenderStringStringArrayVisible() {
TopLevelCommand tlc = new TopLevelCommand();
CommandSender sender = mock(CommandSender.class);
String[] args = {"v"};
List<String> opList = tlc.tabComplete(sender, "top", args);
assertFalse(opList.isEmpty());
assertEquals("visible", opList.get(0));
}
/**
* Test method for {@link world.bentobox.bentobox.api.commands.CompositeCommand#tabComplete(org.bukkit.command.CommandSender, java.lang.String, java.lang.String[])}.
*/
@Test
public void testTabCompleteCommandSenderStringStringArrayHidden() {
TopLevelCommand tlc = new TopLevelCommand();
CommandSender sender = mock(CommandSender.class);
String[] args = {"h"};
List<String> opList = tlc.tabComplete(sender, "top", args);
assertEquals(1, opList.size());
assertEquals("help", opList.get(0)); // Only help
}
/**
* Test method for {@link world.bentobox.bentobox.api.commands.CompositeCommand#tabComplete(org.bukkit.command.CommandSender, java.lang.String, java.lang.String[])}.
*/
@Test
public void testTabCompleteCommandSenderStringStringArrayInvisible() {
TopLevelCommand tlc = new TopLevelCommand();
CommandSender sender = mock(CommandSender.class);
String[] args = {"i"};
List<String> opList = tlc.tabComplete(sender, "top", args);
assertTrue(opList.isEmpty());
}
/**
* Test method for {@link world.bentobox.bentobox.api.commands.CompositeCommand#showHelp(world.bentobox.bentobox.api.commands.CompositeCommand, world.bentobox.bentobox.api.user.User)}.
*/
@Test
public void testShowHelp() {
// Only the visible command should show in help
TopLevelCommand tlc = new TopLevelCommand();
tlc.showHelp(tlc, user);
verify(user).sendMessage(eq("commands.help.header"), eq(TextVariables.LABEL), eq("commands.help.console"));
verify(user).sendMessage(eq("commands.help.syntax-no-parameters"), eq("[usage]"), eq("/top"), eq(TextVariables.DESCRIPTION), eq("top.description"));
verify(user).sendMessage(eq("commands.help.syntax-no-parameters"), eq("[usage]"), eq("/top visible"), eq(TextVariables.DESCRIPTION), eq("visible.description"));
verify(user, never()).sendMessage(eq("commands.help.syntax-no-parameters"), eq("[usage]"), eq("/top hidden"), eq(TextVariables.DESCRIPTION), anyString());
verify(user, never()).sendMessage(eq("commands.help.syntax-no-parameters"), eq("[usage]"), eq("/top hidden2"), eq(TextVariables.DESCRIPTION), anyString());
verify(user).sendMessage(eq("commands.help.end"));
}
class TopLevelCommand extends CompositeCommand {
public TopLevelCommand() {
super("top");
}
@Override
public void setup() {
this.setParametersHelp("top.parameters");
this.setDescription("top.description");
new VisibleCommand(this);
new HiddenCommand(this);
new Hidden2Command(this);
}
@Override
public boolean execute(User user, String label, List<String> args) {
return true;
}
}
class VisibleCommand extends CompositeCommand {
public VisibleCommand(CompositeCommand parent) {
super(parent, "visible");
}
@Override
public void setup() {
this.setParametersHelp("visible.parameters");
this.setDescription("visible.description");
}
@Override
public boolean execute(User user, String label, List<String> args) {
return true;
}
}
class HiddenCommand extends CompositeCommand {
public HiddenCommand(CompositeCommand parent) {
super(parent, "hidden");
}
@Override
public void setup() {
this.setHidden(true);
}
@Override
public boolean execute(User user, String label, List<String> args) {
return true;
}
}
class Hidden2Command extends CompositeCommand {
public Hidden2Command(CompositeCommand parent) {
super(parent, "invisible");
}
@Override
public void setup() {
this.setHidden(true);
this.setParametersHelp("invisible.parameters");
this.setDescription("invisible.description");
}
@Override
public boolean execute(User user, String label, List<String> args) {
return true;
}
}
}