From bb5d06dd9515305c68c0931f177d27bef9785937 Mon Sep 17 00:00:00 2001 From: erickgonzalez Date: Tue, 14 Nov 2023 12:12:20 -0600 Subject: [PATCH] #22534 include in 23.01.9 --- .../velocity/services/PageLoader.java | 15 +---- .../velocity/servlet/VelocityModeHandler.java | 3 +- .../business/HTMLPageAssetAPI.java | 22 ++++++- .../business/HTMLPageAssetAPIImpl.java | 59 +++++++++++++++---- hotfix_tracking.md | 1 + 5 files changed, 73 insertions(+), 27 deletions(-) diff --git a/dotCMS/src/main/java/com/dotcms/rendering/velocity/services/PageLoader.java b/dotCMS/src/main/java/com/dotcms/rendering/velocity/services/PageLoader.java index 002e9e1419b3..838bbf529325 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/velocity/services/PageLoader.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/velocity/services/PageLoader.java @@ -212,19 +212,8 @@ public InputStream writeObject(final VelocityResourceKey key) throws DotDataExce private HTMLPageAsset getPage(VelocityResourceKey key) throws DotDataException, DotSecurityException { - try { - return APILocator.getHTMLPageAssetAPI() - .fromContentlet(APILocator.getContentletAPI() - .findContentletByIdentifier(key.id1, key.mode.showLive, - ConversionUtils.toLong(key.language), - key.variant, sysUser(), true)); - } catch (DotStateException e) { - return APILocator.getHTMLPageAssetAPI() - .fromContentlet(APILocator.getContentletAPI() - .findContentletByIdentifier(key.id1, key.mode.showLive, - ConversionUtils.toLong(key.language), - VariantAPI.DEFAULT_VARIANT.name(), sysUser(), true)); - } + return (HTMLPageAsset) APILocator.getHTMLPageAssetAPI() + .findByIdLanguageVariantFallback(key.id1, ConversionUtils.toLong(key.language), key.variant, key.mode.showLive, sysUser(), true); } diff --git a/dotCMS/src/main/java/com/dotcms/rendering/velocity/servlet/VelocityModeHandler.java b/dotCMS/src/main/java/com/dotcms/rendering/velocity/servlet/VelocityModeHandler.java index 1f319d6fcbf4..07ec4055dba4 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/velocity/servlet/VelocityModeHandler.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/velocity/servlet/VelocityModeHandler.java @@ -152,10 +152,11 @@ public static final VelocityModeHandler modeHandler(final PageMode mode, final H public final Template getTemplate(final IHTMLPage page, final PageMode mode) { final String currentVariantId = WebAPILocator.getVariantWebAPI().currentVariantId(); + final long viewingLang = WebAPILocator.getLanguageWebAPI().getLanguage(request).getId(); return VelocityUtil.getEngine().getTemplate( VelocityResourceKey.getHTMLPageFilePath(page.getIdentifier(), mode, - page.getLanguageId(), currentVariantId)); + viewingLang, currentVariantId)); } } diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/htmlpageasset/business/HTMLPageAssetAPI.java b/dotCMS/src/main/java/com/dotmarketing/portlets/htmlpageasset/business/HTMLPageAssetAPI.java index 81836c596801..87bef03f00ca 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/htmlpageasset/business/HTMLPageAssetAPI.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/htmlpageasset/business/HTMLPageAssetAPI.java @@ -301,7 +301,7 @@ public void setContainersRemap(List containersReMap) { /** * Returns page based on identifier and respects the language fallback settings - * @param id + * @param identifier * @param tryLang * @param live * @param user @@ -314,7 +314,7 @@ public void setContainersRemap(List containersReMap) { /** * Returns page based on identifier and respects the language fallback settings - * @param id identifier of page + * @param identifier identifier of page * @param tryLang requested language * @param live live or working version of page * @param user user to perform operation with @@ -326,4 +326,22 @@ public void setContainersRemap(List containersReMap) { IHTMLPage findByIdLanguageFallback(String identifier, long tryLang, boolean live, User user, boolean respectFrontEndPermissions) throws DotDataException, DotSecurityException; + /** + * Returns page based on identifier and respects the language fallback settings + * If a non-standard variant is passed in and it is not found, this will also fall back to the + * DEFAULT variant as well. + * @param identifier identifier of page + * @param tryLang requested language + * @param tryVariant requested variant + * @param live live or working version of page + * @param user user to perform operation with + * @param respectFrontEndPermissions respect front end permissions + * + * @return + * @throws DotDataException + * @throws DotSecurityException + */ + IHTMLPage findByIdLanguageVariantFallback(String identifier, long tryLang, String tryVariant, boolean live, User user, boolean respectFrontEndPermissions) + throws DotSecurityException; + } diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/htmlpageasset/business/HTMLPageAssetAPIImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/htmlpageasset/business/HTMLPageAssetAPIImpl.java index f5c57975b770..c1da39a99e23 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/htmlpageasset/business/HTMLPageAssetAPIImpl.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/htmlpageasset/business/HTMLPageAssetAPIImpl.java @@ -13,16 +13,11 @@ import com.dotcms.mock.request.MockSessionRequest; import com.dotcms.mock.response.BaseResponse; import com.dotcms.rendering.velocity.servlet.VelocityModeHandler; +import com.dotcms.variant.VariantAPI; import com.dotmarketing.beans.Host; import com.dotmarketing.beans.Identifier; import com.dotmarketing.beans.MultiTree; -import com.dotmarketing.business.APILocator; -import com.dotmarketing.business.CacheLocator; -import com.dotmarketing.business.DotStateException; -import com.dotmarketing.business.IdentifierAPI; -import com.dotmarketing.business.PermissionAPI; -import com.dotmarketing.business.UserAPI; -import com.dotmarketing.business.VersionableAPI; +import com.dotmarketing.business.*; import com.dotmarketing.business.web.LanguageWebAPI; import com.dotmarketing.business.web.WebAPILocator; import com.dotmarketing.common.db.DotConnect; @@ -63,12 +58,20 @@ import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotNull; + +import io.vavr.Lazy; +import io.vavr.control.Try; import org.apache.velocity.exception.ResourceNotFoundException; public class HTMLPageAssetAPIImpl implements HTMLPageAssetAPI { - public static final String CMS_INDEX_PAGE = Config.getStringProperty("CMS_INDEX_PAGE", "index"); + + public static final Lazy CMS_INDEX_PAGE = Lazy.of(() -> Config.getStringProperty( + "CMS_INDEX_PAGE", "index")); + public static final Lazy DEFAULT_PAGE_TO_DEFAULT_LANGUAGE = + Lazy.of(() -> Config.getBooleanProperty("DEFAULT_PAGE_TO_DEFAULT_LANGUAGE", true)); public static final String DEFAULT_HTML_PAGE_ASSET_STRUCTURE_HOST_FIELD = "defaultHTMLPageAssetStructure"; private final PermissionAPI permissionAPI; @@ -193,7 +196,7 @@ public HTMLPageAsset fromContentlet(Contentlet con) { try { contentletAPI.copyProperties((Contentlet) pa, con.getMap()); } catch (Exception e) { - throw new DotStateException("Page Copy Failed", e); + throw new DotStateException("Page Copy Failed on Contentlet Inode: " + con.getInode(), e); } pa.setHost(con.getHost()); if(UtilMethods.isSet(con.getFolder())){ @@ -289,12 +292,12 @@ public IHTMLPage getPageByPath(String uri, Host host, Long languageId, Boolean l private Identifier getIndexPageIdentifier(final String folderURI, final Host host) { final String indexPageUri = folderURI.endsWith("/") ? - folderURI + CMS_INDEX_PAGE : folderURI + "/" + CMS_INDEX_PAGE; + folderURI + CMS_INDEX_PAGE.get() : folderURI + "/" + CMS_INDEX_PAGE.get(); try { return identifierAPI.find(host, indexPageUri); } catch (Exception e) { - Logger.error(this.getClass(), "Unable to find" + folderURI); + Logger.error(this.getClass(), "Unable to find folder URI: " + folderURI); return null; } } @@ -911,5 +914,39 @@ private IHTMLPage findPageInDefaultLanguageDifferentThanProvided(String identifi return htmlPage; } + @Override + public IHTMLPage findByIdLanguageVariantFallback(@NotNull final String identifier, final long tryLang, + @NotNull final String tryVariant, final boolean live, + @NotNull final User user, + final boolean respectFrontEndPermissions) throws DotSecurityException { + final long defaultLang = APILocator.getLanguageAPI().getDefaultLanguage().getId(); + final boolean fallbackLang = tryLang != defaultLang && DEFAULT_PAGE_TO_DEFAULT_LANGUAGE.get(); + + // given lang and variant + HTMLPageAsset asset = Try.of(() -> fromContentlet(contentletAPI + .findContentletByIdentifier(identifier, live, tryLang, tryVariant, APILocator.systemUser(), true))).getOrNull(); + + if (asset == null) { + + // given lang and DEFAULT varian + asset = Try.of(() -> fromContentlet(contentletAPI.findContentletByIdentifier(identifier, live, tryLang, VariantAPI.DEFAULT_VARIANT.name(), APILocator.systemUser(), true))).getOrNull(); + } + + if (asset == null && fallbackLang) { + // DEFAULT lang and given variant + asset = Try.of(() -> fromContentlet(contentletAPI.findContentletByIdentifier(identifier, live, defaultLang, tryVariant, APILocator.systemUser(), true))).getOrNull(); + if (asset == null) { + // DEFAULT lang and DEFAULT variant + asset = Try.of(() -> fromContentlet(contentletAPI.findContentletByIdentifier(identifier, live, defaultLang, VariantAPI.DEFAULT_VARIANT.name(), APILocator.systemUser(), true))).getOrNull(); + } + } + if (asset == null) { + throw new DotStateException("Unable to find page that matches. id:" + identifier + " lang:" + tryLang + " variant:" + tryVariant); + } + + permissionAPI.checkPermission(asset, PermissionLevel.READ, user); + return asset; + } + } diff --git a/hotfix_tracking.md b/hotfix_tracking.md index 60baec0481ff..f6668c0c9036 100644 --- a/hotfix_tracking.md +++ b/hotfix_tracking.md @@ -158,3 +158,4 @@ This maintenance release includes the following code fixes: 129. https://github.com/dotCMS/core/issues/18575 : DotCMS uses incorrect language when adding new content #18575 130. https://github.com/dotCMS/core/issues/21529 : The JSON viewtool does not support valid JSON types, only strings #21529 +131. https://github.com/dotCMS/core/issues/22534 : Caching empty containers in the Velocity2 cache when accessing in a language where the content doesn't exist #22534