-
Notifications
You must be signed in to change notification settings - Fork 467
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#22857 refreshing block editor contentlet reference #22867
Merged
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
3e02f1c
#22857 initial draft and ideas
jdotcms e662762
#22857 initial draft and ideas
jdotcms 70a2df6
#22857 initial draft and ideas
jdotcms 699d6ea
#22857 initial draft and ideas
jdotcms cbf6f2f
#22857 initial draft and ideas
jdotcms c68edba
#22857 initial draft and ideas
jdotcms 938b2ed
#22857 final changes
jdotcms 3df7c1b
˜#22857 adding the story block api
jdotcms f6943a8
#22857 the refresh happens now even on cached contentlets
jdotcms b6c60cc
#22857 adding some minor changes
jdotcms 717a0c3
#22857 adding unit test for update references
jdotcms 20e3c74
#22857 unit test for getDependencies
jdotcms ca9d726
#22857 unit test for getDependencies
jdotcms d97d420
#22857 merge master done
jdotcms 99d45de
#22857 adding feedback
jdotcms 76ea624
#22857 adding more feedback
jdotcms 2adf9bb
#22857 adding more feedback
jdotcms 24cd314
#22857 rolling back some config
jdotcms 47b3303
#22857 rolling back some config
jdotcms 22a08d3
#22857 adding some logging
jdotcms 8184737
Merge branch 'master' of github.com:dotCMS/core into issue-22857-refr…
jdotcms 3ffc900
#22857 merge master done
jdotcms 27cf06a
Rename var
fmontes d5435b6
#22857 adding a fix for searching by query when need to refresh the b…
jdotcms 09e5bbf
Merge branch 'issue-22857-refresh-content-editor' of github.com:dotCM…
jdotcms 6e71166
#22857 adding some flag to control when refresh or not
jdotcms 11571ef
Merge remote-tracking branch 'origin/release-22.10.1' into issue-2285…
jcastro-dotcms File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
186 changes: 186 additions & 0 deletions
186
dotCMS/src/integration-test/java/com/dotcms/contenttype/business/StoryBlockAPITest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
package com.dotcms.contenttype.business; | ||
|
||
import com.dotcms.IntegrationTestBase; | ||
import com.dotcms.content.business.json.ContentletJsonHelper; | ||
import com.dotcms.contenttype.model.type.ContentType; | ||
import com.dotcms.datagen.ContentletDataGen; | ||
import com.dotcms.util.IntegrationTestInitService; | ||
import com.dotmarketing.business.APILocator; | ||
import com.dotmarketing.exception.DotDataException; | ||
import com.dotmarketing.exception.DotSecurityException; | ||
import com.dotmarketing.portlets.contentlet.model.Contentlet; | ||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.liferay.util.StringPool; | ||
import io.vavr.Tuple2; | ||
import io.vavr.control.Try; | ||
import org.junit.Assert; | ||
import org.junit.BeforeClass; | ||
import org.junit.Test; | ||
|
||
import java.util.LinkedHashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
|
||
/** | ||
* Test for {@link StoryBlockAPI} | ||
* @author jsanca | ||
*/ | ||
public class StoryBlockAPITest extends IntegrationTestBase { | ||
|
||
private static final String JSON = | ||
|
||
"{\n" + | ||
" \"type\":\"doc\",\n" + | ||
" \"content\":[\n" + | ||
" {\n" + | ||
" \"type\":\"horizontalRule\"\n" + | ||
" },\n" + | ||
" {\n" + | ||
" \"type\":\"heading\",\n" + | ||
" \"content\":[\n" + | ||
" {\n" + | ||
" \"text\":\"Heading\",\n" + | ||
" \"type\":\"text\"\n" + | ||
" },\n" + | ||
" {\n" + | ||
" \"marks\":[\n" + | ||
" {\n" + | ||
" \"type\":\"italic\"\n" + | ||
" }\n" + | ||
" ],\n" + | ||
" \"text\":\" 1\",\n" + | ||
" \"type\":\"text\"\n" + | ||
" }\n" + | ||
" ],\n" + | ||
" \"attrs\":{\n" + | ||
" \"textAlign\":\"left\",\n" + | ||
" \"level\":1\n" + | ||
" }\n" + | ||
" },\n" + | ||
" {\n" + | ||
" \"type\":\"paragraph\",\n" + | ||
" \"content\":[\n" + | ||
" {\n" + | ||
" \"text\":\"Paragraph\",\n" + | ||
" \"type\":\"text\"\n" + | ||
" },\n" + | ||
" {\n" + | ||
" \"marks\":[\n" + | ||
" {\n" + | ||
" \"type\":\"bold\"\n" + | ||
" }\n" + | ||
" ],\n" + | ||
" \"text\":\" yeah\",\n" + | ||
" \"type\":\"text\"\n" + | ||
" }\n" + | ||
" ],\n" + | ||
" \"attrs\":{\n" + | ||
" \"textAlign\":\"left\"\n" + | ||
" }\n" + | ||
" }\n" + | ||
" ]\n" + | ||
" }"; | ||
|
||
|
||
|
||
@BeforeClass | ||
public static void prepare() throws Exception { | ||
//Setting web app environment | ||
IntegrationTestInitService.getInstance().init(); | ||
} | ||
|
||
/** | ||
* Method to test: {@link StoryBlockAPI#refreshStoryBlockValueReferences(Object)} | ||
* Given Scenario: This will create a story block contentlet, adds a rich content and retrieve the json. | ||
* Then, will update the rich content previously added, the story block contentlet should reflect the new rich text changed. | ||
* ExpectedResult: The new json will reflect the rich text changes | ||
* | ||
*/ | ||
@Test | ||
public void test_refresh_references() throws DotDataException, DotSecurityException, JsonProcessingException { | ||
|
||
//1) create a rich text contentlet with some initial values | ||
final ContentType contentTypeRichText = APILocator.getContentTypeAPI(APILocator.systemUser()).find("webPageContent"); | ||
final Contentlet richTextContentlet = new ContentletDataGen(contentTypeRichText).setProperty("title","Title1").setProperty("body","Body1").nextPersisted(); | ||
|
||
// 2) add the contentlet to the static story block created previously | ||
final Object newStoryBlockJson = APILocator.getStoryBlockAPI().addContentlet(JSON, richTextContentlet); | ||
|
||
// 3) convert the json to map, to start the test | ||
final Map newStoryBlockMap = ContentletJsonHelper.INSTANCE.get().objectMapper() | ||
.readValue(Try.of(() -> newStoryBlockJson.toString()) | ||
.getOrElse(StringPool.BLANK), LinkedHashMap.class); | ||
|
||
Assert.assertNotNull(newStoryBlockMap); | ||
final List contentList = (List) newStoryBlockMap.get("content"); | ||
final Optional<Object> firstContentletMap = contentList.stream() | ||
.filter(content -> "dotContent".equals(Map.class.cast(content).get("type"))).findFirst(); | ||
|
||
Assert.assertTrue(firstContentletMap.isPresent()); | ||
final Map contentletMap = (Map) Map.class.cast(Map.class.cast(firstContentletMap.get()).get(StoryBlockAPI.ATTRS_KEY)).get(StoryBlockAPI.DATA_KEY); | ||
Assert.assertEquals(contentletMap.get("identifier"), richTextContentlet.getIdentifier()); | ||
Assert.assertEquals(contentletMap.get("title"), richTextContentlet.getStringProperty("title")); | ||
Assert.assertEquals(contentletMap.get("body"), richTextContentlet.getStringProperty("body")); | ||
|
||
// 4) checkout/publish the contentlet in order to do new changes | ||
final Contentlet newRichTextContentlet = APILocator.getContentletAPI().checkout(richTextContentlet.getInode(), APILocator.systemUser(), false); | ||
newRichTextContentlet.setProperty("title","Title2"); | ||
newRichTextContentlet.setProperty("body","Body2"); | ||
APILocator.getContentletAPI().publish( | ||
APILocator.getContentletAPI().checkin(newRichTextContentlet, APILocator.systemUser(), false), APILocator.systemUser(), false); | ||
|
||
// 5) ask for refreshing references, the new changes of the rich text contentlet should be reflected on the json | ||
final StoryBlockReferenceResult refreshResult = APILocator.getStoryBlockAPI().refreshStoryBlockValueReferences(newStoryBlockJson); | ||
|
||
// 6) check if the results are ok. | ||
Assert.assertTrue(refreshResult.isRefreshed()); | ||
Assert.assertNotNull(refreshResult.getValue()); | ||
final Map refreshedStoryBlockMap = ContentletJsonHelper.INSTANCE.get().objectMapper() | ||
.readValue(Try.of(() -> refreshResult.getValue().toString()) | ||
.getOrElse(StringPool.BLANK), LinkedHashMap.class); | ||
final List refreshedContentList = (List) refreshedStoryBlockMap.get("content"); | ||
final Optional<Object> refreshedfirstContentletMap = refreshedContentList.stream() | ||
.filter(content -> "dotContent".equals(Map.class.cast(content).get("type"))).findFirst(); | ||
|
||
Assert.assertTrue(refreshedfirstContentletMap.isPresent()); | ||
final Map refreshedContentletMap = (Map) Map.class.cast(Map.class.cast(refreshedfirstContentletMap.get()).get(StoryBlockAPI.ATTRS_KEY)).get(StoryBlockAPI.DATA_KEY); | ||
Assert.assertEquals(refreshedContentletMap.get("identifier"), newRichTextContentlet.getIdentifier()); | ||
Assert.assertEquals("Title2", newRichTextContentlet.getStringProperty("title")); | ||
Assert.assertEquals("Body2", newRichTextContentlet.getStringProperty("body")); | ||
} | ||
|
||
/** | ||
* Method to test: {@link StoryBlockAPI#getDependencies(Object)} | ||
* Given Scenario: Creates a story block and adds 3 contentlets | ||
* ExpectedResult: The contentlets added should be retrieved | ||
* | ||
*/ | ||
@Test | ||
public void test_get_dependencies() throws DotDataException, DotSecurityException, JsonProcessingException { | ||
|
||
//1) create a rich text contentlets with some initial values | ||
final ContentType contentTypeRichText = APILocator.getContentTypeAPI(APILocator.systemUser()).find("webPageContent"); | ||
final Contentlet richTextContentlet1 = new ContentletDataGen(contentTypeRichText).setProperty("title","Title1").setProperty("body","Body1").nextPersisted(); | ||
final Contentlet richTextContentlet2 = new ContentletDataGen(contentTypeRichText).setProperty("title","Title1").setProperty("body","Body1").nextPersisted(); | ||
final Contentlet richTextContentlet3 = new ContentletDataGen(contentTypeRichText).setProperty("title","Title1").setProperty("body","Body1").nextPersisted(); | ||
|
||
// 2) adds the contentlets to the static story block created previously | ||
final Object newStoryBlockJson1 = APILocator.getStoryBlockAPI().addContentlet(JSON, richTextContentlet1); | ||
final Object newStoryBlockJson2 = APILocator.getStoryBlockAPI().addContentlet(newStoryBlockJson1, richTextContentlet2); | ||
final Object newStoryBlockJson3 = APILocator.getStoryBlockAPI().addContentlet(newStoryBlockJson2, richTextContentlet3); | ||
|
||
// 3) convert the json to map, to start the test | ||
final Map newStoryBlockMap = ContentletJsonHelper.INSTANCE.get().objectMapper() | ||
.readValue(Try.of(() -> newStoryBlockJson3.toString()) | ||
.getOrElse(StringPool.BLANK), LinkedHashMap.class); | ||
|
||
Assert.assertNotNull(newStoryBlockMap); | ||
final List<String> contentletIdList = APILocator.getStoryBlockAPI().getDependencies(newStoryBlockJson3); | ||
Assert.assertNotNull(contentletIdList); | ||
Assert.assertEquals(3, contentletIdList.size()); | ||
Assert.assertTrue(contentletIdList.contains(richTextContentlet1.getIdentifier())); | ||
Assert.assertTrue(contentletIdList.contains(richTextContentlet2.getIdentifier())); | ||
Assert.assertTrue(contentletIdList.contains(richTextContentlet3.getIdentifier())); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
dotCMS/src/main/java/com/dotcms/contenttype/business/StoryBlockAPI.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package com.dotcms.contenttype.business; | ||
|
||
import com.dotmarketing.portlets.contentlet.model.Contentlet; | ||
import com.google.common.collect.ImmutableSet; | ||
|
||
import java.util.List; | ||
import java.util.Set; | ||
|
||
/** | ||
* Api to handle dependencies, references and so for the StoryBlock (content editor) | ||
* @author jsanca | ||
*/ | ||
public interface StoryBlockAPI { | ||
|
||
String CONTENT_KEY = "content"; | ||
String TYPE_KEY = "type"; | ||
String ATTRS_KEY = "attrs"; | ||
String DATA_KEY = "data"; | ||
String IDENTIFIER_KEY = "identifier"; | ||
String INODE_KEY = "inode"; | ||
String LANGUAGE_ID_KEY = "languageId"; | ||
|
||
/** | ||
* Encapsulates the allowed types for contentlets on the story block | ||
*/ | ||
Set<String> allowedTypes = new ImmutableSet.Builder<String>().add("dotContent","dotImage").build(); | ||
|
||
/** | ||
* Analyzed all {@link com.dotcms.contenttype.model.field.StoryBlockField} fields, refreshing all contentlet which | ||
* inode is different to the live inode on the system. | ||
* @param contentlet {@link Contentlet} to refresh | ||
* @return Contentlet content refreshed | ||
*/ | ||
StoryBlockReferenceResult refreshReferences(final Contentlet contentlet); | ||
|
||
/** | ||
* Refresh the story block references for a story block json (The argument storyBlockValue will be converted to string and parse as json) | ||
* @param storyBlockValue Object | ||
* @return Tuple2 boolean if there was something to refresh, the object is the new object refreshed; if not anything to refresh return the same object sent as an argument | ||
*/ | ||
StoryBlockReferenceResult refreshStoryBlockValueReferences(final Object storyBlockValue); | ||
|
||
/** | ||
* For each {@link com.dotcms.contenttype.model.field.StoryBlockField} field, retrieve contentlet ids referrer on the | ||
* story block json. | ||
* @param contentlet {@link Contentlet} | ||
* @return List of identifier (empty list if not any contentlet) | ||
*/ | ||
List<String> getDependencies (final Contentlet contentlet); | ||
|
||
/** | ||
* Get the dependencies for a story block json /Users/jsanca/gitsources/new-core2/core/dotCMS/src/main/java/com/dotcms/contenttype/business/StoryBlockAPI.java | ||
* @param storyBlockValue Object | ||
* @return List of contentlets on the story block referrer | ||
*/ | ||
List<String> getDependencies (final Object storyBlockValue); | ||
|
||
/** | ||
* Adds a contentlet to the story block value | ||
* @param storyBlockValue {@link Object} | ||
* @param contentlet {@link Contentlet} | ||
* @return Object | ||
*/ | ||
Object addContentlet(final Object storyBlockValue, final Contentlet contentlet); | ||
|
||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we can move this json into a json file