diff --git a/.github/workflows/maven-build.yml b/.github/workflows/maven-build.yml index c85498c1..fc4f02da 100644 --- a/.github/workflows/maven-build.yml +++ b/.github/workflows/maven-build.yml @@ -20,7 +20,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - java: [11, 17] + java: [11, 17, 21] os: [ubuntu-latest] distribution: [temurin] diff --git a/.github/workflows/maven-deploy.yml b/.github/workflows/maven-deploy.yml index 30b8e546..c709b1cc 100644 --- a/.github/workflows/maven-deploy.yml +++ b/.github/workflows/maven-deploy.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Configure GIT run: | diff --git a/.github/workflows/release-from-tag.yml b/.github/workflows/release-from-tag.yml index b66b5ff6..c4aab046 100644 --- a/.github/workflows/release-from-tag.yml +++ b/.github/workflows/release-from-tag.yml @@ -12,7 +12,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ncipollo/release-action@v1 with: body: 'Changes: https://wcm.io/handler/media/changes-report.html' diff --git a/changes.xml b/changes.xml index 8f08fb3d..8297820f 100644 --- a/changes.xml +++ b/changes.xml @@ -23,6 +23,15 @@ xsi:schemaLocation="http://maven.apache.org/changes/1.0.0 http://maven.apache.org/plugins/maven-changes-plugin/xsd/changes-1.0.0.xsd"> + + + MediaHandlerConfig: Make list of allowed IPE editor types configurable (defaults to "image"). + + + DefaultMediaFormatListProvider, MediaFormatValidateServlet: Eliminate usage of org.apache.sling.commons.json. + + + DAM Renditions: Read width/height of rendition lazy, as this can be expensive when not configured properly or Asset metadata is missing for other reasons. diff --git a/pom.xml b/pom.xml index 6daae2cf..82fd0431 100644 --- a/pom.xml +++ b/pom.xml @@ -25,13 +25,13 @@ io.wcm io.wcm.parent_toplevel - 2.2.2 + 2.2.8 io.wcm io.wcm.handler.media - 1.15.8 + 1.16.0 jar Media Handler @@ -49,7 +49,7 @@ handler/media - 2023-09-08T14:08:30Z + 2023-12-18T11:18:37Z @@ -138,7 +138,7 @@ io.wcm io.wcm.testing.aem-mock.junit5 - 5.3.0 + 5.4.2 test @@ -187,7 +187,24 @@ org.skyscreamer jsonassert - 1.5.0 + 1.5.1 + test + + + com.fasterxml.jackson.core + jackson-databind + test + + + com.jayway.jsonpath + json-path + 2.8.0 + test + + + com.jayway.jsonpath + json-path-assert + 2.8.0 test diff --git a/src/main/java/io/wcm/handler/media/format/impl/DefaultMediaFormatListProvider.java b/src/main/java/io/wcm/handler/media/format/impl/DefaultMediaFormatListProvider.java index fd40c1f0..066e1568 100644 --- a/src/main/java/io/wcm/handler/media/format/impl/DefaultMediaFormatListProvider.java +++ b/src/main/java/io/wcm/handler/media/format/impl/DefaultMediaFormatListProvider.java @@ -20,7 +20,9 @@ package io.wcm.handler.media.format.impl; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Set; import javax.servlet.Servlet; @@ -30,12 +32,14 @@ import org.apache.sling.api.SlingHttpServletResponse; import org.apache.sling.api.servlets.HttpConstants; import org.apache.sling.api.servlets.SlingSafeMethodsServlet; -import org.apache.sling.commons.json.JSONArray; -import org.apache.sling.commons.json.JSONException; -import org.apache.sling.commons.json.JSONObject; import org.jetbrains.annotations.NotNull; import org.osgi.service.component.annotations.Component; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.ObjectMapper; + import io.wcm.handler.media.format.MediaFormat; import io.wcm.handler.media.format.MediaFormatHandler; import io.wcm.wcm.commons.contenttype.ContentType; @@ -50,47 +54,41 @@ "sling.servlet.resourceTypes=sling/servlet/default", "sling.servlet.methods=" + HttpConstants.METHOD_GET }) -@SuppressWarnings("deprecation") public final class DefaultMediaFormatListProvider extends SlingSafeMethodsServlet { private static final long serialVersionUID = 1L; + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + @Override protected void doGet(@NotNull SlingHttpServletRequest request, @NotNull SlingHttpServletResponse response) throws ServletException, IOException { - try { - - // get list of media formats for current medialib path - Set mediaFormats = getMediaFormats(request); - - response.setContentType(ContentType.JSON); - - JSONArray mediaFormatList = new JSONArray(); - - if (mediaFormats != null) { - for (MediaFormat mediaFormat : mediaFormats) { - if (!mediaFormat.isInternal()) { - JSONObject mediaFormatItem = new JSONObject(); - mediaFormatItem.put("name", mediaFormat.getName()); - mediaFormatItem.put("text", mediaFormat.toString()); - mediaFormatItem.put("width", mediaFormat.getWidth()); - mediaFormatItem.put("height", mediaFormat.getHeight()); - mediaFormatItem.put("widthMin", mediaFormat.getMinWidth()); - mediaFormatItem.put("heightMin", mediaFormat.getMinHeight()); - mediaFormatItem.put("widthHeightMin", mediaFormat.getMinWidthHeight()); - mediaFormatItem.put("isImage", mediaFormat.isImage()); - mediaFormatItem.put("ratio", mediaFormat.getRatio()); - mediaFormatItem.put("ratioWidth", mediaFormat.getRatioWidthAsDouble()); - mediaFormatItem.put("ratioHeight", mediaFormat.getRatioHeightAsDouble()); - mediaFormatItem.put("ratioDisplayString", mediaFormat.getRatioDisplayString()); - mediaFormatList.put(mediaFormatItem); - } + // get list of media formats for current medialib path + Set mediaFormats = getMediaFormats(request); + + List mediaFormatList = new ArrayList<>(); + if (mediaFormats != null) { + for (MediaFormat mediaFormat : mediaFormats) { + if (!mediaFormat.isInternal()) { + MediaFormatItem mediaFormatItem = new MediaFormatItem(); + mediaFormatItem.name = mediaFormat.getName(); + mediaFormatItem.text = mediaFormat.toString(); + mediaFormatItem.width = mediaFormat.getWidth(); + mediaFormatItem.height = mediaFormat.getHeight(); + mediaFormatItem.widthMin = mediaFormat.getMinWidth(); + mediaFormatItem.heightMin = mediaFormat.getMinHeight(); + mediaFormatItem.widthHeightMin = mediaFormat.getMinWidthHeight(); + mediaFormatItem.isImage = mediaFormat.isImage(); + mediaFormatItem.ratio = mediaFormat.getRatio(); + mediaFormatItem.ratioWidth = mediaFormat.getRatioWidthAsDouble(); + mediaFormatItem.ratioHeight = mediaFormat.getRatioHeightAsDouble(); + mediaFormatItem.ratioDisplayString = mediaFormat.getRatioDisplayString(); + mediaFormatList.add(mediaFormatItem); } } - - response.getWriter().write(mediaFormatList.toString()); - } - catch (JSONException ex) { - throw new ServletException(ex); } + + // serialize to JSON using Jackson + response.setContentType(ContentType.JSON); + response.getWriter().write(OBJECT_MAPPER.writeValueAsString(mediaFormatList)); } protected Set getMediaFormats(SlingHttpServletRequest request) { @@ -103,4 +101,70 @@ protected Set getMediaFormats(SlingHttpServletRequest request) { } } + @JsonInclude(Include.NON_NULL) + static class MediaFormatItem { + private String name; + private String text; + private long width; + private long height; + private long widthMin; + private long heightMin; + private long widthHeightMin; + private boolean isImage; + private double ratio; + private double ratioWidth; + private double ratioHeight; + private String ratioDisplayString; + + public String getName() { + return this.name; + } + + public String getText() { + return this.text; + } + + public long getWidth() { + return this.width; + } + + public long getHeight() { + return this.height; + } + + public long getWidthMin() { + return this.widthMin; + } + + public long getHeightMin() { + return this.heightMin; + } + + public long getWidthHeightMin() { + return this.widthHeightMin; + } + + @JsonProperty("isImage") + public boolean isImage() { + return this.isImage; + } + + public double getRatio() { + return this.ratio; + } + + public double getRatioWidth() { + return this.ratioWidth; + } + + public double getRatioHeight() { + return this.ratioHeight; + } + + public String getRatioDisplayString() { + return this.ratioDisplayString; + } + + } + } diff --git a/src/main/java/io/wcm/handler/media/impl/MediaBuilderImpl.java b/src/main/java/io/wcm/handler/media/impl/MediaBuilderImpl.java index 8aafc328..ddaaac2d 100644 --- a/src/main/java/io/wcm/handler/media/impl/MediaBuilderImpl.java +++ b/src/main/java/io/wcm/handler/media/impl/MediaBuilderImpl.java @@ -356,6 +356,7 @@ private static MediaComponentPropertyResolver getMediaComponentPropertyResolver( } @Override + @SuppressWarnings("PMD.OptimizableToArrayCall") public @NotNull Media build() { if (!pictureSourceSets.isEmpty()) { this.mediaArgs.pictureSources(pictureSourceSets.toArray(new PictureSource[pictureSourceSets.size()])); diff --git a/src/main/java/io/wcm/handler/media/impl/MediaFormatValidateServlet.java b/src/main/java/io/wcm/handler/media/impl/MediaFormatValidateServlet.java index 1dc727eb..340e698b 100644 --- a/src/main/java/io/wcm/handler/media/impl/MediaFormatValidateServlet.java +++ b/src/main/java/io/wcm/handler/media/impl/MediaFormatValidateServlet.java @@ -34,8 +34,6 @@ import org.apache.sling.api.SlingHttpServletResponse; import org.apache.sling.api.servlets.HttpConstants; import org.apache.sling.api.servlets.SlingSafeMethodsServlet; -import org.apache.sling.commons.json.JSONException; -import org.apache.sling.commons.json.JSONObject; import org.apache.sling.servlets.annotations.SlingServletResourceTypes; import org.jetbrains.annotations.NotNull; import org.osgi.service.component.annotations.Component; @@ -43,6 +41,9 @@ import com.day.cq.i18n.I18n; import com.day.cq.wcm.api.Page; import com.day.cq.wcm.api.PageManager; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.databind.ObjectMapper; import io.wcm.handler.media.Media; import io.wcm.handler.media.MediaArgs.MediaFormatOption; @@ -63,7 +64,6 @@ selectors = MediaFormatValidateServlet.SELECTOR, resourceTypes = "sling/servlet/default", methods = HttpConstants.METHOD_GET) -@SuppressWarnings("deprecation") public final class MediaFormatValidateServlet extends SlingSafeMethodsServlet { private static final long serialVersionUID = 1L; @@ -74,6 +74,8 @@ public final class MediaFormatValidateServlet extends SlingSafeMethodsServlet { static final String RP_MEDIA_CROPAUTO = "mediaCropAuto"; static final String RP_MEDIA_REF = "mediaRef"; + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + /** * Prefix for i18n keys to generated messages for media invalid reasons. */ @@ -112,20 +114,15 @@ protected void doGet(@NotNull SlingHttpServletRequest request, @NotNull SlingHtt .build(); // response - try { - JSONObject result = new JSONObject(); - result.put("valid", media.isValid()); - if (!media.isValid()) { - I18n i18n = getI18n(request); - result.put("reason", getI18nText(i18n, getMediaInvalidReasonI18nKeyOrMessage(media))); - result.put("reasonTitle", getI18nText(i18n, ASSET_INVALID_I18N_KEY)); - } - response.setContentType(ContentType.JSON); - response.getWriter().write(result.toString()); - } - catch (JSONException ex) { - throw new ServletException(ex); + ResultResponse result = new ResultResponse(); + result.valid = media.isValid(); + if (!media.isValid()) { + I18n i18n = getI18n(request); + result.reason = getI18nText(i18n, getMediaInvalidReasonI18nKeyOrMessage(media)); + result.reasonTitle = getI18nText(i18n, ASSET_INVALID_I18N_KEY); } + response.setContentType(ContentType.JSON); + response.getWriter().write(OBJECT_MAPPER.writeValueAsString(result)); } private String getMediaInvalidReasonI18nKeyOrMessage(@NotNull Media media) { @@ -157,4 +154,25 @@ private I18n getI18n(SlingHttpServletRequest request) { return new I18n(request); } + @JsonInclude(Include.NON_NULL) + static class ResultResponse { + + private boolean valid; + private String reason; + private String reasonTitle; + + public boolean isValid() { + return this.valid; + } + + public String getReason() { + return this.reason; + } + + public String getReasonTitle() { + return this.reasonTitle; + } + + } + } diff --git a/src/main/java/io/wcm/handler/media/markup/MediaMarkupBuilderUtil.java b/src/main/java/io/wcm/handler/media/markup/MediaMarkupBuilderUtil.java index 520702a5..f11d131a 100644 --- a/src/main/java/io/wcm/handler/media/markup/MediaMarkupBuilderUtil.java +++ b/src/main/java/io/wcm/handler/media/markup/MediaMarkupBuilderUtil.java @@ -19,6 +19,8 @@ */ package io.wcm.handler.media.markup; +import java.util.Set; + import org.apache.commons.lang3.StringUtils; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; @@ -54,6 +56,11 @@ @ProviderType public final class MediaMarkupBuilderUtil { + /** + * List of OOTB IPE editor types for images. + */ + public static final Set DEFAULT_ALLOWED_IPE_EDITOR_TYPES = Set.of("image"); + private MediaMarkupBuilderUtil() { // static methods only } @@ -217,6 +224,18 @@ public static boolean canApplyDragDropSupport(@NotNull MediaRequest mediaRequest */ public static boolean canSetCustomIPECropRatios(@NotNull MediaRequest mediaRequest, @Nullable ComponentContext wcmComponentContext) { + return canSetCustomIPECropRatios(mediaRequest, wcmComponentContext, DEFAULT_ALLOWED_IPE_EDITOR_TYPES); + } + + /** + * Implements check whether to set customized IPE cropping ratios as described in {@link IPERatioCustomize}. + * @param mediaRequest Media request + * @param wcmComponentContext WCM component context + * @param allowedIpeEditorTypes Allowed editor types for image IPE (in-place editor). + * @return true if customized IP cropping ratios can be set + */ + public static boolean canSetCustomIPECropRatios(@NotNull MediaRequest mediaRequest, + @Nullable ComponentContext wcmComponentContext, @NotNull Set allowedIpeEditorTypes) { EditConfig editConfig = null; InplaceEditingConfig ipeConfig = null; @@ -227,7 +246,7 @@ public static boolean canSetCustomIPECropRatios(@NotNull MediaRequest mediaReque ipeConfig = editConfig.getInplaceEditingConfig(); } if (editConfig == null || ipeConfig == null - || !StringUtils.equals(ipeConfig.getEditorType(), "image")) { + || !allowedIpeEditorTypes.contains(ipeConfig.getEditorType())) { // no image IPE activated - never customize crop ratios return false; } diff --git a/src/main/java/io/wcm/handler/media/markup/package-info.java b/src/main/java/io/wcm/handler/media/markup/package-info.java index 18d04e27..d4cd4e2b 100644 --- a/src/main/java/io/wcm/handler/media/markup/package-info.java +++ b/src/main/java/io/wcm/handler/media/markup/package-info.java @@ -20,5 +20,5 @@ /** * Default media markup builder implementations. */ -@org.osgi.annotation.versioning.Version("1.5.1") +@org.osgi.annotation.versioning.Version("1.6") package io.wcm.handler.media.markup; diff --git a/src/main/java/io/wcm/handler/media/spi/MediaHandlerConfig.java b/src/main/java/io/wcm/handler/media/spi/MediaHandlerConfig.java index 07ca3522..22393d0d 100644 --- a/src/main/java/io/wcm/handler/media/spi/MediaHandlerConfig.java +++ b/src/main/java/io/wcm/handler/media/spi/MediaHandlerConfig.java @@ -21,6 +21,7 @@ import java.util.Collections; import java.util.List; +import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; @@ -30,6 +31,7 @@ import io.wcm.handler.media.MediaNameConstants; import io.wcm.handler.media.markup.DummyImageMediaMarkupBuilder; +import io.wcm.handler.media.markup.MediaMarkupBuilderUtil; import io.wcm.handler.media.markup.SimpleImageMediaMarkupBuilder; import io.wcm.handler.mediasource.dam.DamMediaSource; import io.wcm.sling.commons.caservice.ContextAwareService; @@ -247,6 +249,14 @@ public boolean enforceVirtualRenditions() { return false; } + /** + * @return Allowed editor types for image IPE (in-place editor). + * By default, only the OOTB "image" editor type is supported. + */ + public @NotNull Set allowedIpeEditorTypes() { + return MediaMarkupBuilderUtil.DEFAULT_ALLOWED_IPE_EDITOR_TYPES; + } + /** * Get root path for picking assets using path field widgets. * @param page Context page diff --git a/src/main/java/io/wcm/handler/media/spi/package-info.java b/src/main/java/io/wcm/handler/media/spi/package-info.java index 1891b307..766484be 100644 --- a/src/main/java/io/wcm/handler/media/spi/package-info.java +++ b/src/main/java/io/wcm/handler/media/spi/package-info.java @@ -20,5 +20,5 @@ /** * SPI for configuring and tailoring media handler processing. */ -@org.osgi.annotation.versioning.Version("1.7") +@org.osgi.annotation.versioning.Version("1.8") package io.wcm.handler.media.spi; diff --git a/src/main/java/io/wcm/handler/mediasource/dam/DamMediaSource.java b/src/main/java/io/wcm/handler/mediasource/dam/DamMediaSource.java index bfd68d90..e386d60e 100644 --- a/src/main/java/io/wcm/handler/mediasource/dam/DamMediaSource.java +++ b/src/main/java/io/wcm/handler/mediasource/dam/DamMediaSource.java @@ -221,7 +221,7 @@ public void setCustomIPECropRatios(@NotNull HtmlElement element, @NotNull Med } if (componentContext != null - && MediaMarkupBuilderUtil.canSetCustomIPECropRatios(mediaRequest, componentContext)) { + && MediaMarkupBuilderUtil.canSetCustomIPECropRatios(mediaRequest, componentContext, mediaHandlerConfig.allowedIpeEditorTypes())) { // overlay IPE config with cropping ratios for each media format with a valid ratio CroppingRatios croppingRatios = new CroppingRatios(mediaFormatHandler); Set mediaFormatNames = croppingRatios.getMediaFormatsForCropping(mediaRequest); diff --git a/src/main/java/io/wcm/handler/mediasource/dam/impl/dynamicmedia/DynamicMediaSupportServiceImpl.java b/src/main/java/io/wcm/handler/mediasource/dam/impl/dynamicmedia/DynamicMediaSupportServiceImpl.java index 035245e1..23d2e693 100644 --- a/src/main/java/io/wcm/handler/mediasource/dam/impl/dynamicmedia/DynamicMediaSupportServiceImpl.java +++ b/src/main/java/io/wcm/handler/mediasource/dam/impl/dynamicmedia/DynamicMediaSupportServiceImpl.java @@ -251,10 +251,10 @@ public boolean isValidateSmartCropRenditionSizes() { * @return true if publish mode should be forced */ private boolean forcePublishMode(@Nullable UrlMode urlMode) { - return (urlMode == UrlModes.FULL_URL_PUBLISH - || urlMode == UrlModes.FULL_URL_PUBLISH_FORCENONSECURE - || urlMode == UrlModes.FULL_URL_PUBLISH_FORCESECURE - || urlMode == UrlModes.FULL_URL_PUBLISH_PROTOCOLRELATIVE); + return urlMode != null && (urlMode.equals(UrlModes.FULL_URL_PUBLISH) + || urlMode.equals(UrlModes.FULL_URL_PUBLISH_FORCENONSECURE) + || urlMode.equals(UrlModes.FULL_URL_PUBLISH_FORCESECURE) + || urlMode.equals(UrlModes.FULL_URL_PUBLISH_PROTOCOLRELATIVE)); } } diff --git a/src/test/java/io/wcm/handler/media/format/impl/DefaultMediaFormatListProviderTest.java b/src/test/java/io/wcm/handler/media/format/impl/DefaultMediaFormatListProviderTest.java index 03077391..c0233ae3 100644 --- a/src/test/java/io/wcm/handler/media/format/impl/DefaultMediaFormatListProviderTest.java +++ b/src/test/java/io/wcm/handler/media/format/impl/DefaultMediaFormatListProviderTest.java @@ -19,13 +19,17 @@ */ package io.wcm.handler.media.format.impl; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItem; -import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; + import io.wcm.handler.media.testcontext.AppAemContext; import io.wcm.handler.media.testcontext.DummyMediaFormats; import io.wcm.testing.mock.aem.junit5.AemContext; @@ -48,9 +52,11 @@ void testGet() throws Exception { underTest.service(context.request(), context.response()); String response = context.response().getOutputAsString(); - assertTrue(StringUtils.contains(response, "\"" + DummyMediaFormats.EDITORIAL_1COL.getName() + "\"")); - assertTrue(StringUtils.contains(response, "\"" + DummyMediaFormats.EDITORIAL_2COL.getName() + "\"")); - assertTrue(StringUtils.contains(response, "\"" + DummyMediaFormats.EDITORIAL_3COL.getName() + "\"")); + + DocumentContext json = JsonPath.parse(response); + assertThat(json, hasJsonPath("$[*].name", hasItem(DummyMediaFormats.EDITORIAL_1COL.getName()))); + assertThat(json, hasJsonPath("$[*].name", hasItem(DummyMediaFormats.EDITORIAL_2COL.getName()))); + assertThat(json, hasJsonPath("$[*].name", hasItem(DummyMediaFormats.EDITORIAL_3COL.getName()))); } } diff --git a/src/test/java/io/wcm/handler/media/impl/ipeconfig/IPEConfigResourceProviderTest.java b/src/test/java/io/wcm/handler/media/impl/ipeconfig/IPEConfigResourceProviderTest.java index c13c6def..dc5c43ec 100644 --- a/src/test/java/io/wcm/handler/media/impl/ipeconfig/IPEConfigResourceProviderTest.java +++ b/src/test/java/io/wcm/handler/media/impl/ipeconfig/IPEConfigResourceProviderTest.java @@ -116,6 +116,7 @@ public Component answer(InvocationOnMock invocation) throws Throwable { when(mediaFormatHandler.getMediaFormat(SHOWROOM_STANDARD.getName())).thenReturn(SHOWROOM_STANDARD); when(mediaFormatHandler.getMediaFormat(NONFIXED_RAW.getName())).thenReturn(NONFIXED_RAW); } + @Test @SuppressWarnings("null") void testCustomIPEConfig() { diff --git a/src/test/java/io/wcm/handler/media/markup/MediaMarkupBuilderUtilTest.java b/src/test/java/io/wcm/handler/media/markup/MediaMarkupBuilderUtilTest.java index 5fb10126..9b3b6637 100644 --- a/src/test/java/io/wcm/handler/media/markup/MediaMarkupBuilderUtilTest.java +++ b/src/test/java/io/wcm/handler/media/markup/MediaMarkupBuilderUtilTest.java @@ -23,8 +23,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.util.Set; + import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ResourceResolver; @@ -40,6 +43,9 @@ import com.day.cq.wcm.api.Page; import com.day.cq.wcm.api.PageManager; import com.day.cq.wcm.api.components.ComponentContext; +import com.day.cq.wcm.api.components.EditConfig; +import com.day.cq.wcm.api.components.EditContext; +import com.day.cq.wcm.api.components.InplaceEditingConfig; import io.wcm.handler.commons.dom.Image; import io.wcm.handler.media.Dimension; @@ -71,6 +77,14 @@ class MediaMarkupBuilderUtilTest { private SlingHttpServletRequest request; @Mock private ComponentContext componentContext; + @Mock + private Resource componentResource; + @Mock + private EditContext editContext; + @Mock + private EditConfig editConfig; + @Mock + private InplaceEditingConfig inplaceEditingConfig; @BeforeEach @SuppressWarnings("null") @@ -80,6 +94,12 @@ void setUp() throws Exception { when(request.getResource()).thenReturn(resource); when(pageManager.getContainingPage(resource)).thenReturn(page); when(request.getParameter(DiffService.REQUEST_PARAM_DIFF_TO)).thenReturn(VERSION_LABEL); + when(componentContext.getResource()).thenReturn(componentResource); + when(componentResource.getResourceResolver()).thenReturn(resolver); + when(componentContext.getEditContext()).thenReturn(editContext); + when(editContext.getEditConfig()).thenReturn(editConfig); + when(editConfig.getInplaceEditingConfig()).thenReturn(inplaceEditingConfig); + when(inplaceEditingConfig.getEditorType()).thenReturn("image"); } @Test @@ -149,4 +169,51 @@ void testCanApplyDragDropSupport_DragDropSupport_Auto() { assertTrue(MediaMarkupBuilderUtil.canApplyDragDropSupport(mediaRequest, componentContext)); } + @Test + void testCanSetCustomIPECropRatios_ALWAYS() { + MediaRequest mediaRequest = new MediaRequest("/content/dam/path", new MediaArgs().ipeRatioCustomize(IPERatioCustomize.ALWAYS)); + assertTrue(MediaMarkupBuilderUtil.canSetCustomIPECropRatios(mediaRequest, componentContext)); + } + + @Test + void testCanSetCustomIPECropRatios_ALWAYS_CustomEditorType_Mismatch() { + when(inplaceEditingConfig.getEditorType()).thenReturn("custom"); + MediaRequest mediaRequest = new MediaRequest("/content/dam/path", new MediaArgs().ipeRatioCustomize(IPERatioCustomize.ALWAYS)); + assertFalse(MediaMarkupBuilderUtil.canSetCustomIPECropRatios(mediaRequest, componentContext)); + } + + @Test + void testCanSetCustomIPECropRatios_ALWAYS_CustomEditorType_Match() { + when(inplaceEditingConfig.getEditorType()).thenReturn("custom"); + MediaRequest mediaRequest = new MediaRequest("/content/dam/path", new MediaArgs().ipeRatioCustomize(IPERatioCustomize.ALWAYS)); + assertTrue(MediaMarkupBuilderUtil.canSetCustomIPECropRatios(mediaRequest, componentContext, Set.of("image", "custom"))); + } + + @Test + void testCanSetCustomIPECropRatios_NEVER() { + MediaRequest mediaRequest = new MediaRequest("/content/dam/path", new MediaArgs().ipeRatioCustomize(IPERatioCustomize.NEVER)); + assertFalse(MediaMarkupBuilderUtil.canSetCustomIPECropRatios(mediaRequest, componentContext)); + } + + @Test + void testCanSetCustomIPECropRatios_AUTO() { + MediaRequest mediaRequest = new MediaRequest("/content/dam/path", new MediaArgs().ipeRatioCustomize(IPERatioCustomize.AUTO)); + assertTrue(MediaMarkupBuilderUtil.canSetCustomIPECropRatios(mediaRequest, componentContext)); + } + + @Test + void testCanSetCustomIPECropRatios_AUTO_IPEConfigPath() { + MediaRequest mediaRequest = new MediaRequest("/content/dam/path", new MediaArgs().ipeRatioCustomize(IPERatioCustomize.AUTO)); + when(inplaceEditingConfig.getConfigPath()).thenReturn("/apps/components/comp1"); + assertTrue(MediaMarkupBuilderUtil.canSetCustomIPECropRatios(mediaRequest, componentContext)); + } + + @Test + void testCanSetCustomIPECropRatios_AUTO_ExistingRatios() { + MediaRequest mediaRequest = new MediaRequest("/content/dam/path", new MediaArgs().ipeRatioCustomize(IPERatioCustomize.AUTO)); + when(inplaceEditingConfig.getConfigPath()).thenReturn("/apps/components/comp1"); + when(resolver.getResource("/apps/components/comp1/plugins/crop/aspectRatios")).thenReturn(mock(Resource.class)); + assertFalse(MediaMarkupBuilderUtil.canSetCustomIPECropRatios(mediaRequest, componentContext)); + } + }