5656import com .dotcms .rendering .velocity .services .ContentletLoader ;
5757import com .dotcms .rendering .velocity .services .PageLoader ;
5858import com .dotcms .rest .AnonymousAccess ;
59+ import com .dotcms .contenttype .util .StoryBlockUtil ;
60+ import com .dotcms .util .JsonUtil ;
5961import com .dotcms .rest .api .v1 .temp .DotTempFile ;
6062import com .dotcms .rest .api .v1 .temp .TempFileAPI ;
6163import com .dotcms .storage .FileMetadataAPI ;
6668import com .dotcms .util .ConversionUtils ;
6769import com .dotcms .util .DotPreconditions ;
6870import com .dotcms .util .FunctionUtils ;
69- import com .dotcms .util .JsonUtil ;
7071import com .dotcms .util .ThreadContextUtil ;
7172import com .dotcms .util .xstream .XStreamHandler ;
7273import com .dotcms .variant .VariantAPI ;
@@ -7549,7 +7550,7 @@ public static void parseDate(final Contentlet contentlet,
75497550 field .getVelocityVarName ());
75507551 }
75517552 } else {
7552-
7553+
75537554 contentlet .setDateProperty (field .getVelocityVarName (), null );
75547555 }
75557556 } else if (field .isRequired () && value == null ) {
@@ -7738,6 +7739,40 @@ public void validateContentlet(final Contentlet contentlet, final List<Category>
77387739 Logger .warn (this , String .format ("String Field [%s] is required" , field .getVelocityVarName ()));
77397740 continue ;
77407741 }
7742+ } else if (field .getFieldType ().equals (Field .FieldType .STORY_BLOCK_FIELD .toString ())) {
7743+ // Story Block validation - handle both JSON and legacy WYSIWYG content during migration
7744+ if (fieldValue == null ) {
7745+ cveBuilder .addRequiredField (field , "null" );
7746+ hasError = true ;
7747+ Logger .warn (this , String .format ("Story Block Field [%s] is required" , field .getVelocityVarName ()));
7748+ continue ;
7749+ } else if (!(fieldValue instanceof String )) {
7750+ cveBuilder .addBadTypeField (field , fieldValue != null ? fieldValue .toString () : "null" );
7751+ hasError = true ;
7752+ Logger .warn (this , String .format ("Story Block Field [%s] must be a String, but got: %s" ,
7753+ field .getVelocityVarName (), fieldValue .getClass ().getSimpleName ()));
7754+ continue ;
7755+ } else {
7756+ String stringValue = (String ) fieldValue ;
7757+ if (JsonUtil .isValidJSON (stringValue )) {
7758+ // Valid JSON - validate as Story Block
7759+ if (StoryBlockUtil .isEmptyStoryBlock (stringValue )) {
7760+ cveBuilder .addRequiredField (field , fieldValue .toString ());
7761+ hasError = true ;
7762+ Logger .warn (this , String .format ("Story Block Field [%s] is required" , field .getVelocityVarName ()));
7763+ continue ;
7764+ }
7765+ } else {
7766+ // Legacy WYSIWYG content (including malformed JSON) - use simple string validation for backward compatibility
7767+ if (stringValue .trim ().isEmpty ()) {
7768+ cveBuilder .addRequiredField (field , fieldValue .toString ());
7769+ hasError = true ;
7770+ Logger .warn (this , String .format ("Story Block Field [%s] is required" , field .getVelocityVarName ()));
7771+ continue ;
7772+ }
7773+ // Otherwise, let legacy WYSIWYG content (including malformed JSON) pass validation during migration
7774+ }
7775+ }
77417776 } else if (fieldValue instanceof String ) {
77427777 String s1 = (String ) fieldValue ;
77437778 if (!UtilMethods .isSet (s1 .trim ())
@@ -8105,7 +8140,7 @@ private void validateBinary(final File binary, final String fieldName, final Fie
81058140 UtilMethods .prettyByteify (maxLength ))))
81068141 .addBadTypeField (legacyField , String .valueOf (fileLength ))
81078142 .build ();
8108- Logger .warn (this , String .format ("Name of Binary field [%s] has a length: %d but the max length is: %d" ,
8143+ Logger .warn (this , String .format ("Name of Binary field [%s] has a length: %d but the max length is: %d" ,
81098144 fieldName , fileLength , maxLength ));
81108145 throw cve ;
81118146 }
@@ -8323,6 +8358,7 @@ private void validateSite(Contentlet contentlet) {
83238358 }
83248359
83258360
8361+
83268362 @ CloseDBIfOpened
83278363 @ Override
83288364 public void validateContentletNoRels (final Contentlet contentlet ,
@@ -8383,6 +8419,7 @@ public void validateContentlet(final Contentlet contentlet,
83838419 validateContentlet (contentlet ,contentRelationships , cats , false );
83848420 }
83858421
8422+
83868423 @ CloseDBIfOpened
83878424 @ Override
83888425 public void validateContentlet (final Contentlet contentlet ,
@@ -8480,7 +8517,7 @@ private void validateRelationships(final Contentlet contentlet,
84808517
84818518 if (!foundInRelationships && !hasExistingRelatedContent ) {
84828519 hasError = true ;
8483- Logger .error (this , String .format ("Required %s relationship [%s] is not present for contentlet [%s]" ,
8520+ Logger .error (this , String .format ("Required %s relationship [%s] is not present for contentlet [%s]" ,
84848521 (checkParent ? "child" : "parent" ), rel .getRelationTypeValue (), contentletId ));
84858522 builder .addRequiredRelationship (rel , new ArrayList <>());
84868523 }
@@ -8526,7 +8563,7 @@ private void validateRelationships(final Contentlet contentlet,
85268563 && isRelationshipParent ) {
85278564 if (relationship .isChildRequired () && contentsInRelationship .isEmpty ()) {
85288565 hasError = true ;
8529- Logger .error (this , String .format ("Error in Contentlet [%s]: Child relationship [%s] is required." ,
8566+ Logger .error (this , String .format ("Error in Contentlet [%s]: Child relationship [%s] is required." ,
85308567 contentletId , relationship .getRelationTypeValue ()));
85318568 builder .addRequiredRelationship (relationship , contentsInRelationship );
85328569 }
@@ -8564,14 +8601,14 @@ private void validateRelationships(final Contentlet contentlet,
85648601 contentsInRelationship );
85658602 }
85668603 } catch (final DotDataException e ) {
8567- Logger .error (this , String .format ("An error occurred when retrieving information from related Contentlet [%s]" ,
8604+ Logger .error (this , String .format ("An error occurred when retrieving information from related Contentlet [%s]" ,
85688605 contentInRelationship .getIdentifier ()), e );
85698606 }
85708607 }
85718608 } else if (APILocator .getRelationshipAPI ().isChild (relationship , contentType )) {
85728609 if (relationship .isParentRequired () && contentsInRelationship .isEmpty ()) {
85738610 hasError = true ;
8574- Logger .error (this , String .format ("Error in Contentlet [%s]: Parent relationship [%s] is required." ,
8611+ Logger .error (this , String .format ("Error in Contentlet [%s]: Parent relationship [%s] is required." ,
85758612 contentletId , relationship .getRelationTypeValue ()));
85768613 builder .addRequiredRelationship (relationship , contentsInRelationship );
85778614 }
@@ -8587,7 +8624,7 @@ private void validateRelationships(final Contentlet contentlet,
85878624 final String parentIds = contentsInRelationship .stream ()
85888625 .map (Contentlet ::getIdentifier )
85898626 .collect (java .util .stream .Collectors .joining (", " ));
8590- final String errorMessage = String .format ("ERROR! Child content [%s] is already related to another parent content [%s]" ,
8627+ final String errorMessage = String .format ("ERROR! Child content [%s] is already related to another parent content [%s]" ,
85918628 contentletId , parentIds );
85928629 Logger .error (this , errorMessage );
85938630 hasError = true ;
@@ -8605,14 +8642,14 @@ private void validateRelationships(final Contentlet contentlet,
86058642 && !contentInRelationship .getContentTypeId ().equalsIgnoreCase (
86068643 relationship .getParentStructureInode ())) {
86078644 hasError = true ;
8608- Logger .error (this , String .format ("Content Type of Contentlet [%s] does not match the Content Type in relationship [%s]" ,
8645+ Logger .error (this , String .format ("Content Type of Contentlet [%s] does not match the Content Type in relationship [%s]" ,
86098646 contentletId , relationship .getRelationTypeValue ()));
86108647 builder .addInvalidContentRelationship (relationship , contentsInRelationship );
86118648 }
86128649 }
86138650 } else {
86148651 hasError = true ;
8615- Logger .error (this , String .format ("Relationship [%s] is neither parent nor child of Contentlet [%s]" ,
8652+ Logger .error (this , String .format ("Relationship [%s] is neither parent nor child of Contentlet [%s]" ,
86168653 relationship .getRelationTypeValue (), contentletId ));
86178654 builder .addBadRelationship (relationship , contentsInRelationship );
86188655 }
@@ -8637,7 +8674,7 @@ private boolean isValidOneToOneRelationship(final Contentlet contentlet,
86378674 List <Contentlet > contentsInRelationshipSameLanguage = groupContentletsByLanguage (contentsInRelationship );
86388675 //Trying to relate more than one piece of content
86398676 if (contentsInRelationshipSameLanguage .size () > 1 ) {
8640- Logger .error (this , String .format ("Error in Contentlet [%s]: Relationship [%s] has been defined as One to One" ,
8677+ Logger .error (this , String .format ("Error in Contentlet [%s]: Relationship [%s] has been defined as One to One" ,
86418678 contentlet .getIdentifier (), relationship .getRelationTypeValue ()));
86428679 builder .addBadCardinalityRelationship (relationship , contentsInRelationship );
86438680 return false ;
@@ -8651,13 +8688,13 @@ private boolean isValidOneToOneRelationship(final Contentlet contentlet,
86518688 .getSystemUser (), true , 1 , 0 , null );
86528689 if (relatedContents .size () > 0 && !relatedContents .get (0 ).getIdentifier ()
86538690 .equals (contentlet .getIdentifier ())) {
8654- Logger .error (this , String .format ("Error in related Contentlet [%s]: Relationship [%s] has been defined as One to One" ,
8691+ Logger .error (this , String .format ("Error in related Contentlet [%s]: Relationship [%s] has been defined as One to One" ,
86558692 relatedContents .get (0 ).getIdentifier (), relationship .getRelationTypeValue ()));
86568693 builder .addBadCardinalityRelationship (relationship , contentsInRelationship );
86578694 return false ;
86588695 }
86598696 } catch (final DotDataException e ) {
8660- Logger .error (this , String .format ("An error occurred when retrieving information from related Contentlet [%s]" ,
8697+ Logger .error (this , String .format ("An error occurred when retrieving information from related Contentlet [%s]" ,
86618698 contentsInRelationship .get (0 ).getIdentifier ()), e );
86628699 builder .addInvalidContentRelationship (relationship , contentsInRelationship );
86638700 return false ;
0 commit comments