From a343172383dbe5a1c103ca3a865f4374eaf5296c Mon Sep 17 00:00:00 2001
From: freddyDOTCMS <147462678+freddyDOTCMS@users.noreply.github.com>
Date: Mon, 2 Dec 2024 17:29:59 -0600
Subject: [PATCH] Issue 30285 clean up the unique fields table (#30798)
### Proposed Changes
* Create a Listener to listen when a Contentlet or a FIeld is deleted
and then we can clean the unique_fields table up
https://github.com/dotCMS/core/pull/30798/files#diff-615b3dd949e41009affc1f2921cfe0c6569a1302deec3469d834f6163d7104a8R138
* Create new Method in the UniqueFieldValidationStrategy to clean up the
table
https://github.com/dotCMS/core/pull/30798/files#diff-445f8d01aa4de058eaaf883e573d17ef1123b1e74a9a98120ac156b78f4c6522R131
https://github.com/dotCMS/core/pull/30798/files#diff-445f8d01aa4de058eaaf883e573d17ef1123b1e74a9a98120ac156b78f4c6522R162
* Create method to update the unique_fields table data when a Contentlet
is publish or unpublish
https://github.com/dotCMS/core/pull/30798/files#diff-445f8d01aa4de058eaaf883e573d17ef1123b1e74a9a98120ac156b78f4c6522R141-R153
* Implemenetd all this new methods in the
DBUniqueFieldValidationStrategy
https://github.com/dotCMS/core/pull/30798/files#diff-445f8d01aa4de058eaaf883e573d17ef1123b1e74a9a98120ac156b78f4c6522R141-R153
---------
Co-authored-by: fabrizzio-dotCMS
---
.../config/DotInitializationService.java | 4 +
.../business/ESContentFactoryImpl.java | 3 +-
.../contenttype/business/FieldAPIImpl.java | 2 +-
.../UniqueFieldValidationStrategy.java | 44 +-
.../DBUniqueFieldValidationStrategy.java | 103 +++-
.../extratable/UniqueFieldCriteria.java | 19 +-
.../extratable/UniqueFieldDataBaseUtil.java | 146 ++++-
.../extratable/UniqueFieldsTableCleaner.java | 97 +++
.../UniqueFieldsTableCleanerInitializer.java | 30 +
.../model/field/event/FieldDeletedEvent.java | 14 +-
.../com/dotcms/variant/VariantAPIImpl.java | 6 +-
.../DeleteContentletVersionInfoEvent.java | 31 +
.../dotmarketing/business/VersionableAPI.java | 4 +-
.../business/VersionableAPIImpl.java | 39 +-
.../test/java/com/dotcms/UnitTestBase.java | 11 +
.../track/collectors/FilesCollectorTest.java | 3 +-
.../elasticsearch/ESQueryCacheTest.java | 4 +-
.../com/dotcms/DataProviderWeldRunner.java | 2 +-
.../java/com/dotcms/JUnit4WeldRunner.java | 2 +-
.../business/ESContentletAPIImplTest.java | 556 +++++++++++++++++-
.../business/ESMappingAPITest.java | 5 +-
.../business/FieldAPIImplIntegrationTest.java | 80 ++-
.../DBUniqueFieldValidationStrategyTest.java | 2 +-
.../test/ContentTypeAPIImplTest.java | 15 +-
.../remote/bundler/DependencyBundlerTest.java | 5 +-
.../junit/CustomDataProviderRunner.java | 16 +-
.../java/com/dotcms/junit/MainBaseSuite.java | 4 +-
.../util/IntegrationTestInitService.java | 11 +
28 files changed, 1154 insertions(+), 104 deletions(-)
create mode 100644 dotCMS/src/main/java/com/dotcms/contenttype/business/uniquefields/extratable/UniqueFieldsTableCleaner.java
create mode 100644 dotCMS/src/main/java/com/dotcms/contenttype/business/uniquefields/extratable/UniqueFieldsTableCleanerInitializer.java
create mode 100644 dotCMS/src/main/java/com/dotmarketing/business/DeleteContentletVersionInfoEvent.java
diff --git a/dotCMS/src/main/java/com/dotcms/config/DotInitializationService.java b/dotCMS/src/main/java/com/dotcms/config/DotInitializationService.java
index b4e7f5ac1e4c..1d9b4da3ab36 100644
--- a/dotCMS/src/main/java/com/dotcms/config/DotInitializationService.java
+++ b/dotCMS/src/main/java/com/dotcms/config/DotInitializationService.java
@@ -5,7 +5,10 @@
import com.dotcms.api.system.event.PayloadVerifierFactoryInitializer;
import com.dotcms.api.system.event.SystemEventProcessorFactoryInitializer;
import com.dotcms.business.SystemTableInitializer;
+import com.dotcms.cdi.CDIUtils;
import com.dotcms.contenttype.business.ContentTypeInitializer;
+import com.dotcms.contenttype.business.uniquefields.UniqueFieldValidationStrategyResolver;
+import com.dotcms.contenttype.business.uniquefields.extratable.UniqueFieldsTableCleanerInitializer;
import com.dotcms.rendering.velocity.events.ExceptionHandlersInitializer;
import com.dotcms.system.event.local.business.LocalSystemEventSubscribersInitializer;
import com.dotcms.util.ReflectionUtils;
@@ -132,6 +135,7 @@ private Set getInternalInitializers() {
new DefaultVariantInitializer(),
new SystemTableInitializer(),
new EmbeddingsInitializer(),
+ CDIUtils.getBeanThrows(UniqueFieldsTableCleanerInitializer.class),
new AnalyticsInitializer()
);
} // getInternalInitializers.
diff --git a/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ESContentFactoryImpl.java b/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ESContentFactoryImpl.java
index f1302003b92d..61de303f746e 100644
--- a/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ESContentFactoryImpl.java
+++ b/dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ESContentFactoryImpl.java
@@ -622,8 +622,7 @@ protected void delete(List contentlets, boolean deleteIdentifier) th
}
if(verInfo.get().getWorkingInode().equals(contentlet.getInode()))
APILocator.getVersionableAPI()
- .deleteContentletVersionInfo(contentlet.getIdentifier(),
- contentlet.getLanguageId());
+ .deleteContentletVersionInfoByLanguage(contentlet);
}
delete(contentlet.getInode());
}
diff --git a/dotCMS/src/main/java/com/dotcms/contenttype/business/FieldAPIImpl.java b/dotCMS/src/main/java/com/dotcms/contenttype/business/FieldAPIImpl.java
index b507bfe83ff2..8825e97669e8 100644
--- a/dotCMS/src/main/java/com/dotcms/contenttype/business/FieldAPIImpl.java
+++ b/dotCMS/src/main/java/com/dotcms/contenttype/business/FieldAPIImpl.java
@@ -778,7 +778,7 @@ public void delete(final Field field, final User user) throws DotDataException,
}
CleanUpFieldReferencesJob.triggerCleanUpJob(field, user);
- localSystemEventsAPI.notify(new FieldDeletedEvent(field.variable()));
+ localSystemEventsAPI.notify(new FieldDeletedEvent(field));
}
diff --git a/dotCMS/src/main/java/com/dotcms/contenttype/business/uniquefields/UniqueFieldValidationStrategy.java b/dotCMS/src/main/java/com/dotcms/contenttype/business/uniquefields/UniqueFieldValidationStrategy.java
index 1c5363404a68..2dbead470238 100644
--- a/dotCMS/src/main/java/com/dotcms/contenttype/business/uniquefields/UniqueFieldValidationStrategy.java
+++ b/dotCMS/src/main/java/com/dotcms/contenttype/business/uniquefields/UniqueFieldValidationStrategy.java
@@ -4,6 +4,7 @@
import com.dotcms.contenttype.model.field.Field;
import com.dotcms.contenttype.model.type.ContentType;
import com.dotcms.util.DotPreconditions;
+import com.dotmarketing.beans.VersionInfo;
import com.dotmarketing.business.APILocator;
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.exception.DotSecurityException;
@@ -102,7 +103,6 @@ void innerValidate(final Contentlet contentlet, final Field field, final Object
default void afterSaved(final Contentlet contentlet, final boolean isNew) throws DotDataException, DotSecurityException {
// Default implementation does nothing
}
-
default void recalculate(final Field field, final boolean uniquePerSite) throws UniqueFieldValueDuplicatedException {
// Default implementation does nothing
}
@@ -120,4 +120,46 @@ default void validateField(final Field field) {
}
}
+ /**
+ * Clean the Extra unique validation field table after a {@link Contentlet} have been removed.
+ * We need to remove all the unique values of this {@link Contentlet} and {@link com.dotmarketing.portlets.languagesmanager.model.Language}
+ * from the extra table.
+ *
+ * @param contentlet
+ */
+ default void cleanUp(final Contentlet contentlet, final boolean deleteAllVariant) throws DotDataException {
+ //Default implementation do nothing
+ }
+
+ /**
+ * Method call after publish a {@link Contentlet} it allow the {@link UniqueFieldValidationStrategy} do any extra
+ * work that it need it.
+ *
+ * @param inode Published {@link Contentlet}'s inode
+ */
+ default void afterPublish(final String inode) {
+ //Default implementation do nothing
+ }
+
+ /**
+ * Method call after unpublished a {@link Contentlet} it allow thw {@link UniqueFieldValidationStrategy} do any extra
+ * work that it need it.
+ *
+ * @param versionInfo {@link Contentlet}'s {@link VersionInfo} before un publish
+ */
+ default void afterUnpublish(final VersionInfo versionInfo){
+ //Default implementation do nothing
+ }
+
+ /**
+ * Method called after delete a Unique {@link Field}, to allow the {@link UniqueFieldValidationStrategy} do any extra
+ * work that it need it.
+ *
+ * @param field deleted field
+ * @throws DotDataException
+ */
+ default void cleanUp(final Field field) throws DotDataException {
+ //Default implementation do nothing
+ }
+
}
diff --git a/dotCMS/src/main/java/com/dotcms/contenttype/business/uniquefields/extratable/DBUniqueFieldValidationStrategy.java b/dotCMS/src/main/java/com/dotcms/contenttype/business/uniquefields/extratable/DBUniqueFieldValidationStrategy.java
index 708d497a2859..cf37368e0f96 100644
--- a/dotCMS/src/main/java/com/dotcms/contenttype/business/uniquefields/extratable/DBUniqueFieldValidationStrategy.java
+++ b/dotCMS/src/main/java/com/dotcms/contenttype/business/uniquefields/extratable/DBUniqueFieldValidationStrategy.java
@@ -9,7 +9,9 @@
import com.dotcms.exception.ExceptionUtil;
import com.dotcms.util.JsonUtil;
import com.dotmarketing.beans.Host;
+import com.dotmarketing.beans.VersionInfo;
import com.dotmarketing.business.APILocator;
+import com.dotmarketing.business.DotStateException;
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.exception.DotRuntimeException;
import com.dotmarketing.exception.DotSecurityException;
@@ -78,6 +80,7 @@ public void innerValidate(final Contentlet contentlet, final Field field, final
.setContentType(contentType)
.setValue(fieldValue)
.setVariantName(contentlet.getVariantId())
+ .setLive(isLive(contentlet))
.build();
insertUniqueValue(uniqueFieldCriteria, contentlet.getIdentifier());
@@ -103,38 +106,41 @@ private static boolean isContentletBeingUpdated(final Contentlet contentlet) {
* is not re-generated as the Contentlet ID is not used in it.
*
* @param contentlet The {@link Contentlet} being updated.
- * @param field The {@link Field} representing the Unique Field.
*
* @throws DotDataException An error occurred when interacting with the database.
*/
@SuppressWarnings("unchecked")
- private void cleanUniqueFieldsUp(final Contentlet contentlet, final Field field) throws DotDataException {
- final Optional