Skip to content

Commit

Permalink
feat(multi-language) #30591 : Create endpoints to feed the Multi-lang…
Browse files Browse the repository at this point in the history
…uage Component for the Edit Contentlet sidebar (#30606)

### Proposed Changes
* A new Endpoint has been added to retrieve the languages that a
contentlet is available on: `/api/v1/content//{identifier}/languages`
* A new Endpoint has been added to retrieve the default language:
`/api/v2/languages/_getdefault`
* The existing Endpoint that retrieved the languages that an HTML Page
is available on has been marked as `Deprecated` -- as well as its
related code -- in order to favor the new Endpoint.
  • Loading branch information
jcastro-dotcms authored Nov 9, 2024
1 parent 20899cc commit 65c8ebb
Show file tree
Hide file tree
Showing 8 changed files with 302 additions and 340 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import com.dotmarketing.portlets.contentlet.model.IndexPolicy;
import com.dotmarketing.portlets.contentlet.transform.DotTransformerBuilder;
import com.dotmarketing.portlets.htmlpageasset.model.IHTMLPage;
import com.dotmarketing.portlets.languagesmanager.business.LanguageAPI;
import com.dotmarketing.portlets.languagesmanager.model.Language;
import com.dotmarketing.portlets.structure.model.ContentletRelationships;
import com.dotmarketing.portlets.structure.model.Relationship;
Expand All @@ -47,6 +48,7 @@
import com.dotmarketing.util.UtilMethods;
import com.dotmarketing.util.json.JSONException;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.liferay.portal.language.LanguageUtil;
import com.liferay.portal.model.User;
import io.swagger.v3.oas.annotations.Operation;
Expand Down Expand Up @@ -77,6 +79,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
import java.util.stream.Collectors;
Expand All @@ -92,29 +95,30 @@ public class ContentResource {
private final ContentletAPI contentletAPI;
private final IdentifierAPI identifierAPI;
private final LanguageWebAPI languageWebAPI;
private final LanguageAPI languageAPI;

private final Lazy<Boolean> isDefaultContentToDefaultLanguageEnabled = Lazy.of(
() -> Config.getBooleanProperty("DEFAULT_CONTENT_TO_DEFAULT_LANGUAGE", false));


public ContentResource() {

this(new WebResource(),
APILocator.getContentletAPI(),
APILocator.getIdentifierAPI(),
WebAPILocator.getLanguageWebAPI());
WebAPILocator.getLanguageWebAPI(),
APILocator.getLanguageAPI());
}

@VisibleForTesting
public ContentResource(final WebResource webResource,
final ContentletAPI contentletAPI,
final IdentifierAPI identifierAPI,
final LanguageWebAPI languageWebAPI) {

final LanguageWebAPI languageWebAPI,
final LanguageAPI languageAPI) {
this.webResource = webResource;
this.contentletAPI = contentletAPI;
this.identifierAPI = identifierAPI;
this.languageWebAPI = languageWebAPI;
this.languageAPI = languageAPI;
}

/**
Expand Down Expand Up @@ -590,5 +594,73 @@ public Response pullRelated(@Context final HttpServletRequest request,
}


/**
* Receives the Identifier of a {@link Contentlet }, returns all the available languages in
* dotCMS and, for each of them, adds a flag indicating whether the Contentlet is available in
* that language or not. This may be particularly useful when requiring the system to provide a
* specific action when a Contentlet is NOT available in a given language. Here's an example of
* how you can use it:
* <pre>
* GET <a href="http://localhost:8080/api/v1/content/${CONTENT_ID}/languages">http://localhost:8080/api/v1/content/${CONTENT_ID}/languages</a>
* </pre>
*
* @param request The current instance of the {@link HttpServletRequest}.
* @param response The current instance of the {@link HttpServletResponse}.
* @param identifier The Identifier of the Contentlet whose available languages will be
* checked.
*
* @return A {@link Response} object containing the list of languages and the flag indicating
* whether the Contentlet is available in such a language or not.
*
* @throws DotDataException An error occurred when interacting with the database.
*/
@GET
@Path("/{identifier}/languages")
@JSONP
@NoCache
@Produces({MediaType.APPLICATION_JSON, "application/javascript"})
public ResponseEntityView<List<ExistingLanguagesForContentletView>> checkContentLanguageVersions(@Context final HttpServletRequest request,
@Context final HttpServletResponse response,
@PathParam("identifier") final String identifier) throws DotDataException {
Logger.debug(this, () -> String.format("Check the languages that Contentlet '%s' is " +
"available on", identifier));
final User user = new WebResource.InitBuilder(webResource).requestAndResponse(request, response)
.rejectWhenNoUser(true)
.requiredBackendUser(false)
.init()
.getUser();
final List<ExistingLanguagesForContentletView> languagesForContent =
this.getExistingLanguagesForContent(identifier, user);
return new ResponseEntityView<>(languagesForContent);
}

/**
* Returns a list of ALL languages in dotCMS and, for each of them, adds a boolean indicating
* whether the specified Contentlet Identifier is available in such a language or not. This is
* particularly useful for the UI layer to be able to easily check what languages a Contentlet
* is available on, and what languages it is not.
*
* @param identifier The Identifier of the {@link Contentlet} whose languages are being
* checked.
* @param user The {@link User} performing this action.
*
* @return The list of languages and the flag indicating whether the Contentlet is available in
* such a language or not.
*
* @throws DotDataException An error occurred when interacting with the database.
*/
private List<ExistingLanguagesForContentletView> getExistingLanguagesForContent(final String identifier, final User user) throws DotDataException {
DotPreconditions.checkNotNull(identifier, "Contentlet ID cannot be null");
DotPreconditions.checkNotNull(user, "User cannot be null");
final ImmutableList.Builder<ExistingLanguagesForContentletView> languagesForContent = new ImmutableList.Builder<>();
final Set<Long> existingContentLanguages =
APILocator.getVersionableAPI().findContentletVersionInfos(identifier)
.stream().map(ContentletVersionInfo::getLang)
.collect(Collectors.toSet());
final List<Language> allLanguages = this.languageAPI.getLanguages();
allLanguages.forEach(language -> languagesForContent.add(new ExistingLanguagesForContentletView(language,
existingContentLanguages.contains(language.getId()))));
return languagesForContent.build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.dotcms.rest.api.v1.content;

import com.dotmarketing.portlets.languagesmanager.model.Language;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
* This View is used to indicate what language a
* {@link com.dotmarketing.portlets.contentlet.model.Contentlet} is available on, and what language
* it is not. This is particularly useful for the UI to be aware of such a situation, and then
* provide the user the option to create it using that language.
*
* @author Jose Castro
* @since Jan 5th, 2023
*/
public class ExistingLanguagesForContentletView extends HashMap<String, Object> implements Serializable {

public ExistingLanguagesForContentletView(final Language language, final boolean translated) {
final Map<String, Object> dataMap = new HashMap<>(language.toMap());
this.putAll(dataMap);
this.put("translated", translated);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
*
* @author Jose Castro
* @since Jan 5th, 2023
*
* @deprecated This class is deprecated and will be removed in a future version of dotCMS.
*/
@Deprecated(since = "Nov 7th, 24", forRemoval = true)
public class ExistingLanguagesForPageView extends HashMap<String, Object> implements Serializable {

public ExistingLanguagesForPageView(final Language language, final boolean translated) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1385,12 +1385,16 @@ public ResponseEntityPageWorkflowActionsView findAvailableActions(@Context final
* whether the page is available in such a language or not.
*
* @throws DotDataException An error occurred when interacting with the database.
* @deprecated This method is deprecated and will be removed in future versions. Please use the
* more generic REST Endpoint
* {@link com.dotcms.rest.api.v1.content.ContentResource#getExistingLanguagesForContent(String, User)} instead.
*/
@GET
@Path("/{pageId}/languages")
@JSONP
@NoCache
@Produces({MediaType.APPLICATION_JSON, "application/javascript"})
@Deprecated(since = "Nov 7th, 24", forRemoval = true)
public Response checkPageLanguageVersions(@Context final HttpServletRequest request,
@Context final HttpServletResponse response,
@PathParam("pageId") final String pageId) throws DotDataException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -568,7 +568,10 @@ private Tuple2<Contentlet, Contentlet> copyContent(final CopyContentletForm copy
* language or not.
*
* @throws DotDataException An error occurred when interacting with the database.
*
* @deprecated This method is deprecated and will be removed in future versions.
*/
@Deprecated(since = "Nov 7th, 24", forRemoval = true)
public List<ExistingLanguagesForPageView> getExistingLanguagesForPage(final String pageId, final User user) throws DotDataException {
DotPreconditions.checkNotNull(pageId, "Page ID cannot be null");
DotPreconditions.checkNotNull(user, "User cannot be null");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -637,4 +637,26 @@ public Response getIsoLanguagesAndCountries (
).build();
}

/**
* Returns the current default {@link Language} in the dotCMS instance.
*
* @param request The current instance of the {@link HttpServletRequest}.
* @param response The current instance of the {@link HttpServletResponse}.
*
* @return A {@link Response} object containing the default {@link Language} in the dotCMS
* instance.
*
* @throws DotDataException An error occurred when retrieving the default {@link Language}.
*/
@GET
@Path("/_getdefault")
@JSONP
@NoCache
@Produces({MediaType.APPLICATION_JSON, "application/javascript"})
public ResponseEntityView<Language> getDefaultLanguage(@Context final HttpServletRequest request,
@Context final HttpServletResponse response) throws DotDataException {
Logger.debug(this, () -> "Retrieving the current default Language");
return new ResponseEntityView<>(this.languageAPI.getDefaultLanguage());
}

}
Loading

0 comments on commit 65c8ebb

Please sign in to comment.