diff --git a/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImpl.java b/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImpl.java index 09f233bc0120..afeb560188e0 100644 --- a/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImpl.java +++ b/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImpl.java @@ -7671,6 +7671,10 @@ public void validateContentlet(final Contentlet contentlet, final List // validate unique if (field.isUnique()) { try { + if (!UtilMethods.isSet(contentlet.getHost())) { + populateHost(contentlet); + } + uniqueFieldValidationStrategyResolver.get().get().validate(contentlet, LegacyFieldTransformer.from(field)); } catch (final UniqueFieldValueDuplicatedException e) { diff --git a/dotcms-integration/src/test/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImplTest.java b/dotcms-integration/src/test/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImplTest.java index dc9bb933b5aa..a61f64e7fd1d 100644 --- a/dotcms-integration/src/test/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImplTest.java +++ b/dotcms-integration/src/test/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImplTest.java @@ -94,6 +94,7 @@ import com.rainerhahnekamp.sneakythrow.Sneaky; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.UseDataProvider; +import io.vavr.control.Try; import org.apache.http.HttpStatus; import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest; import org.elasticsearch.action.support.master.AcknowledgedResponse; @@ -4528,4 +4529,56 @@ public void cleanUpExtraTableAfterDeleteContentType() throws DotDataException, D ESContentletAPIImpl.setFeatureFlagDbUniqueFieldValidation(oldEnabledDataBaseValidation); } } + + /** + * Method to test: {@link ContentletAPI#checkin(Contentlet, User, boolean)} } + * When: try to save a {@link Contentlet} that don't have the Host set already + * Should: populate the Host for the {@link Contentlet} (in this case using the {@link ContentType}'s Host) + * and save the siteId in the supporting_values Json field in the unique_fields table + * + * @throws DotDataException + * @throws DotSecurityException + */ + @Test + public void saveSiteIDRightInSupportingValues() throws DotDataException, DotSecurityException { + final boolean oldEnabledDataBaseValidation = ESContentletAPIImpl.getFeatureFlagDbUniqueFieldValidation(); + + try { + ESContentletAPIImpl.setFeatureFlagDbUniqueFieldValidation(true); + final Host host = new SiteDataGen().nextPersisted(); + + final ContentType contentType = new ContentTypeDataGen() + .host(host) + .nextPersisted(); + + final Language language = new LanguageDataGen().nextPersisted(); + + final Field uniqueTextField = new FieldDataGen() + .contentTypeId(contentType.id()) + .unique(true) + .type(TextField.class) + .nextPersisted(); + + final Contentlet contentlet = new Contentlet(); + contentlet.setLanguageId(language.getId()); + contentlet.setBoolProperty(Contentlet.IS_TEST_MODE, true); + contentlet.setContentTypeId(Try.of(()->APILocator.getContentTypeAPI(APILocator.systemUser()) + .find(contentType.id()).id()).getOrNull()); + contentlet.setProperty(uniqueTextField.variable(), "unique-value"); + + contentlet.setIndexPolicy(IndexPolicy.FORCE); + contentlet.setBoolProperty(Contentlet.DISABLE_WORKFLOW, true); + contentletAPI.checkin(contentlet, user, false); + + final List> results = new DotConnect().setSQL("SELECT * FROM unique_fields WHERE supporting_values->>'" + CONTENT_TYPE_ID_ATTR + "' = ?") + .addParam(contentType.id()) + .loadObjectResults(); + assertEquals(1, results.size()); + + final Map supportingValue = getSupportingValue(results.get(0)); + assertEquals(host.getIdentifier(), supportingValue.get(SITE_ID_ATTR)); + } finally { + ESContentletAPIImpl.setFeatureFlagDbUniqueFieldValidation(oldEnabledDataBaseValidation); + } + } }