From fb53ac17e1f5f4b3d8c7fab03fa29aa07e11f21d Mon Sep 17 00:00:00 2001 From: tastybento Date: Thu, 8 Oct 2020 17:47:54 -0700 Subject: [PATCH] Inserts gamemode name into placeholders before passing to PaceholderAPI (#1514) https://github.com/BentoBoxWorld/BentoBox/issues/1512 Co-authored-by: Florian CUNY --- .../BasicPlaceholderExpansion.java | 1 + .../BentoBoxPlaceholderExpansion.java | 1 + .../placeholders/PlaceholderAPIHook.java | 29 +++- .../placeholders/PlaceholderAPIHookTest.java | 161 ++++++++++++++++++ 4 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 src/test/java/world/bentobox/bentobox/hooks/placeholders/PlaceholderAPIHookTest.java diff --git a/src/main/java/world/bentobox/bentobox/api/placeholders/placeholderapi/BasicPlaceholderExpansion.java b/src/main/java/world/bentobox/bentobox/api/placeholders/placeholderapi/BasicPlaceholderExpansion.java index 85377f26a..448b4058d 100644 --- a/src/main/java/world/bentobox/bentobox/api/placeholders/placeholderapi/BasicPlaceholderExpansion.java +++ b/src/main/java/world/bentobox/bentobox/api/placeholders/placeholderapi/BasicPlaceholderExpansion.java @@ -19,6 +19,7 @@ abstract class BasicPlaceholderExpansion extends PlaceholderExpansion { private Map<@NonNull String, @NonNull PlaceholderReplacer> placeholders; BasicPlaceholderExpansion() { + super(); this.placeholders = new HashMap<>(); } diff --git a/src/main/java/world/bentobox/bentobox/api/placeholders/placeholderapi/BentoBoxPlaceholderExpansion.java b/src/main/java/world/bentobox/bentobox/api/placeholders/placeholderapi/BentoBoxPlaceholderExpansion.java index 8f1a999fc..e2acd7805 100644 --- a/src/main/java/world/bentobox/bentobox/api/placeholders/placeholderapi/BentoBoxPlaceholderExpansion.java +++ b/src/main/java/world/bentobox/bentobox/api/placeholders/placeholderapi/BentoBoxPlaceholderExpansion.java @@ -6,6 +6,7 @@ public class BentoBoxPlaceholderExpansion extends BasicPlaceholderExpansion { private BentoBox plugin; public BentoBoxPlaceholderExpansion(BentoBox plugin) { + super(); this.plugin = plugin; } diff --git a/src/main/java/world/bentobox/bentobox/hooks/placeholders/PlaceholderAPIHook.java b/src/main/java/world/bentobox/bentobox/hooks/placeholders/PlaceholderAPIHook.java index bd563a99d..d1b3c138b 100644 --- a/src/main/java/world/bentobox/bentobox/hooks/placeholders/PlaceholderAPIHook.java +++ b/src/main/java/world/bentobox/bentobox/hooks/placeholders/PlaceholderAPIHook.java @@ -3,6 +3,8 @@ package world.bentobox.bentobox.hooks.placeholders; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.Set; import org.bukkit.entity.Player; @@ -11,6 +13,7 @@ import org.eclipse.jdt.annotation.NonNull; import me.clip.placeholderapi.PlaceholderAPI; import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.addons.Addon; +import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.placeholders.PlaceholderReplacer; import world.bentobox.bentobox.api.placeholders.placeholderapi.AddonPlaceholderExpansion; import world.bentobox.bentobox.api.placeholders.placeholderapi.BentoBoxPlaceholderExpansion; @@ -72,7 +75,6 @@ public class PlaceholderAPIHook extends PlaceholderHook { addonsExpansions.put(addon, addonPlaceholderExpansion); this.addonPlaceholders.computeIfAbsent(addon, k -> new HashSet<>()).add(placeholder); } - addonsExpansions.get(addon).registerPlaceholder(placeholder, replacer); } @@ -108,7 +110,30 @@ public class PlaceholderAPIHook extends PlaceholderHook { @Override @NonNull public String replacePlaceholders(@NonNull Player player, @NonNull String string) { - return PlaceholderAPI.setPlaceholders(player, string); + // Transform [gamemode] in string to the game mode description name, or remove it for the default replacement + String newString = BentoBox.getInstance().getIWM().getAddon(player.getWorld()).map(gm -> + string.replace(TextVariables.GAMEMODE, gm.getDescription().getName()) + ).orElse(removeGMPlaceholder(string)); + return PlaceholderAPI.setPlaceholders(player, newString); + } + + private String removeGMPlaceholder(@NonNull String string) { + String newString = string; + // Get placeholders - TODO: my regex moh=jo isn't good enough to grab only placeholders with [gamemode] in yet! + Matcher m = Pattern.compile("(%)(.*?)(%)").matcher(string); + while (m.find()) { + String ph = m.group(); + if (ph.contains(TextVariables.GAMEMODE)) newString = newString.replace(ph,""); + } + return newString; + } + + /** + * Used for unit testing only + * @param bentoboxExpansion the bentoboxExpansion to set + */ + protected void setBentoboxExpansion(BentoBoxPlaceholderExpansion bentoboxExpansion) { + this.bentoboxExpansion = bentoboxExpansion; } /** diff --git a/src/test/java/world/bentobox/bentobox/hooks/placeholders/PlaceholderAPIHookTest.java b/src/test/java/world/bentobox/bentobox/hooks/placeholders/PlaceholderAPIHookTest.java new file mode 100644 index 000000000..1efa728b2 --- /dev/null +++ b/src/test/java/world/bentobox/bentobox/hooks/placeholders/PlaceholderAPIHookTest.java @@ -0,0 +1,161 @@ +package world.bentobox.bentobox.hooks.placeholders; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Optional; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +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.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; + +import me.clip.placeholderapi.PlaceholderAPI; +import world.bentobox.bentobox.BentoBox; +import world.bentobox.bentobox.api.addons.Addon; +import world.bentobox.bentobox.api.addons.AddonDescription; +import world.bentobox.bentobox.api.addons.GameModeAddon; +import world.bentobox.bentobox.api.placeholders.PlaceholderReplacer; +import world.bentobox.bentobox.api.placeholders.placeholderapi.BentoBoxPlaceholderExpansion; +import world.bentobox.bentobox.managers.IslandWorldManager; + +/** + * @author tastybento + * + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({BentoBox.class, PlaceholderAPI.class, Bukkit.class }) +public class PlaceholderAPIHookTest { + + // Class under test + private PlaceholderAPIHook pah; + @Mock + private BentoBox plugin; + @Mock + private Addon addon; + @Mock + private BentoBoxPlaceholderExpansion bentoboxExpansion; + @Mock + private IslandWorldManager iwm; + @Mock + private GameModeAddon gma; + + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + // Set up plugin + plugin = mock(BentoBox.class); + Whitebox.setInternalState(BentoBox.class, "instance", plugin); + when(plugin.getIWM()).thenReturn(iwm); + when(iwm.getAddon(any())).thenReturn(Optional.of(gma)); + PowerMockito.mockStatic(Bukkit.class, Mockito.RETURNS_MOCKS); + // Desc + AddonDescription desc = new AddonDescription.Builder("main", "name", "1.0").build(); + when(addon.getDescription()).thenReturn(desc); + when(gma.getDescription()).thenReturn(desc); + // PlaceholderAPI + PowerMockito.mockStatic(PlaceholderAPI.class, Mockito.RETURNS_MOCKS); + when(PlaceholderAPI.setPlaceholders(any(Player.class), anyString())).thenAnswer((Answer) i -> i.getArgument(1, String.class)); + pah = new PlaceholderAPIHook(); + // Set a default bentoboxExpansion + pah.setBentoboxExpansion(bentoboxExpansion); + + } + + /** + * Test method for {@link world.bentobox.bentobox.hooks.placeholders.PlaceholderAPIHook#getFailureCause()}. + */ + @Test + public void testGetFailureCause() { + assertEquals("could not register BentoBox's expansion", pah.getFailureCause()); + } + + /** + * Test method for {@link world.bentobox.bentobox.hooks.placeholders.PlaceholderAPIHook#registerPlaceholder(java.lang.String, world.bentobox.bentobox.api.placeholders.PlaceholderReplacer)}. + */ + @Test + public void testRegisterPlaceholderStringPlaceholderReplacer() { + PlaceholderReplacer replacer = mock(PlaceholderReplacer.class); + pah.registerPlaceholder("bentobox.placeholder", replacer); + verify(bentoboxExpansion).registerPlaceholder(eq("bentobox.placeholder"), eq(replacer)); + } + + /** + * Test method for {@link world.bentobox.bentobox.hooks.placeholders.PlaceholderAPIHook#registerPlaceholder(world.bentobox.bentobox.api.addons.Addon, java.lang.String, world.bentobox.bentobox.api.placeholders.PlaceholderReplacer)}. + */ + @Test + public void testRegisterPlaceholderAddonStringPlaceholderReplacer() { + PlaceholderReplacer replacer = mock(PlaceholderReplacer.class); + pah.registerPlaceholder(addon, "testing.placeholder", replacer); + assertTrue(pah.isPlaceholder(addon, "testing.placeholder")); + } + + /** + * Test method for {@link world.bentobox.bentobox.hooks.placeholders.PlaceholderAPIHook#unregisterPlaceholder(java.lang.String)}. + */ + @Test + public void testUnregisterPlaceholderString() { + testRegisterPlaceholderAddonStringPlaceholderReplacer(); + pah.unregisterPlaceholder("testing.placeholder"); + assertTrue(pah.isPlaceholder(addon, "testing.placeholder")); + verify(bentoboxExpansion).unregisterPlaceholder(eq("testing.placeholder")); + } + + /** + * Test method for {@link world.bentobox.bentobox.hooks.placeholders.PlaceholderAPIHook#unregisterPlaceholder(world.bentobox.bentobox.api.addons.Addon, java.lang.String)}. + */ + @Test + public void testUnregisterPlaceholderAddonString() { + testRegisterPlaceholderAddonStringPlaceholderReplacer(); + pah.unregisterPlaceholder(addon, "testing.placeholder"); + assertFalse(pah.isPlaceholder(addon, "testing.placeholder")); + } + + /** + * Test method for {@link world.bentobox.bentobox.hooks.placeholders.PlaceholderAPIHook#isPlaceholder(world.bentobox.bentobox.api.addons.Addon, java.lang.String)}. + */ + @Test + public void testIsPlaceholder() { + testRegisterPlaceholderAddonStringPlaceholderReplacer(); + assertFalse(pah.isPlaceholder(addon, "not.a.placeholder")); + } + + /** + * Test method for {@link world.bentobox.bentobox.hooks.placeholders.PlaceholderAPIHook#replacePlaceholders(org.bukkit.entity.Player, java.lang.String)}. + */ + @Test + public void testReplacePlaceholders() { + assertEquals("This is a %test.name.level% test, with %placeholders%, and %name%", + pah.replacePlaceholders(mock(Player.class), "This is a %test.[gamemode].level% test, with %placeholders%, and %[gamemode]%")); + } + + /** + * Test method for {@link world.bentobox.bentobox.hooks.placeholders.PlaceholderAPIHook#replacePlaceholders(org.bukkit.entity.Player, java.lang.String)}. + */ + @Test + public void testReplacePlaceholdersNonGameWorld() { + when(iwm.getAddon(any())).thenReturn(Optional.empty()); + assertEquals("This is a test, with %placeholders%, and ", + pah.replacePlaceholders(mock(Player.class), "This is a %test.[gamemode].level% test, with %placeholders%, and %[gamemode]%")); + + } + +}