From 220190bdc084b4500845136971b98f3d58de3125 Mon Sep 17 00:00:00 2001 From: freddyDOTCMS <147462678+freddyDOTCMS@users.noreply.github.com> Date: Fri, 13 Dec 2024 08:24:14 -0600 Subject: [PATCH] Issue 30919 unique field setting unique per site field var to a content type with existing content fails (#30936) ### Proposed Changes * If the Contentlet has a Unique Field and the Host is not set then populate the Host https://github.com/dotCMS/core/pull/30936/files#diff-fa1ceaa19618a6b2bbc30e24c6f930b4971f417db50babb748c2e2837ba9eb82R7674 Really I just come back this line I removed this by accident when I implemented the new code https://github.com/dotCMS/core/commit/d6eb7b89563c3c981ee355c84b43536040eb5b0d#diff-fa1ceaa19618a6b2bbc30e24c6f930b4971f417db50babb748c2e2837ba9eb82L7647-L7650 --- .../business/ESContentletAPIImpl.java | 4 ++ .../business/ESContentletAPIImplTest.java | 53 +++++++++++++++++++ 2 files changed, 57 insertions(+) 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); + } + } }