Skip to content

Commit 3a037e6

Browse files
committed
fix: Allow to export portlet settings (attachment and translations) - MEED-9809 - Meeds-io/meeds#3780
Before this fix, attachments and translation for logins portlets (sidebarlogin and loginForm) cannot be exported. This commit ensure to export this information and reread it at display Resolves Meeds-io/meeds#3780
1 parent 0fbad66 commit 3a037e6

5 files changed

Lines changed: 242 additions & 53 deletions

File tree

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
/**
2+
* This file is part of the Meeds project (https://meeds.io/).
3+
*
4+
* Copyright (C) 2020 - 2025 Meeds Association contact@meeds.io
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package io.meeds.layout.plugin.renderer;
21+
22+
import io.meeds.layout.model.PortletInstanceContext;
23+
import io.meeds.layout.model.PortletInstancePreference;
24+
import io.meeds.layout.plugin.PortletInstancePreferencePlugin;
25+
import io.meeds.social.translation.model.TranslationField;
26+
import io.meeds.social.translation.service.TranslationService;
27+
import lombok.SneakyThrows;
28+
import org.apache.commons.codec.binary.Base64;
29+
import org.apache.commons.lang3.StringUtils;
30+
import org.exoplatform.commons.exception.ObjectNotFoundException;
31+
import org.exoplatform.commons.file.model.FileItem;
32+
import org.exoplatform.commons.file.services.FileService;
33+
import org.exoplatform.commons.file.services.FileStorageException;
34+
import org.exoplatform.portal.config.model.Application;
35+
import org.exoplatform.portal.pom.spi.portlet.Portlet;
36+
import org.exoplatform.portal.pom.spi.portlet.Preference;
37+
import org.exoplatform.services.log.ExoLogger;
38+
import org.exoplatform.services.log.Log;
39+
import org.exoplatform.social.attachment.AttachmentService;
40+
import org.exoplatform.social.attachment.model.ObjectAttachmentDetail;
41+
import org.exoplatform.social.attachment.model.ObjectAttachmentList;
42+
import org.json.JSONObject;
43+
import org.springframework.beans.factory.annotation.Autowired;
44+
45+
import java.util.ArrayList;
46+
import java.util.List;
47+
import java.util.Map;
48+
49+
public class CMSPortletInstancePreferencePlugin implements PortletInstancePreferencePlugin {
50+
private static final Log LOG = ExoLogger.getLogger(SidebarLoginPortletInstancePreferencePlugin.class);
51+
52+
private static final String DATA_INIT_PREFERENCE_NAME = "data.init";
53+
54+
private static final String EXPORT_DATA_INIT_PREFERENCE_NAME = "export.data.init";
55+
56+
private static final String EXPORT_DATA_ALT_INIT_PREFERENCE_NAME = "export.data.alt.init";
57+
58+
private static final String EXPORT_DATA_TRANSLATION_INIT_PREFERENCE_NAME = "export.data.translation.init";
59+
60+
private static final String CMS_SETTING_PREFERENCE_NAME = "name";
61+
62+
@Autowired
63+
private AttachmentService attachmentService;
64+
65+
@Autowired
66+
private FileService fileService;
67+
68+
@Autowired
69+
private TranslationService translationService;
70+
71+
public static final String OBJECT_TYPE = "cmsPortlet";
72+
73+
@Override
74+
public String getPortletName() {
75+
return "CMSPortlet";
76+
}
77+
78+
@Override
79+
@SneakyThrows
80+
public List<PortletInstancePreference> generatePreferences(Application application,
81+
Portlet preferences,
82+
PortletInstanceContext portletInstanceContext) {
83+
String settingName = getCmsSettingName(preferences);
84+
List<PortletInstancePreference> result = new ArrayList<>();
85+
preferences.forEach(preference -> {
86+
if (!preference.getName().equals("name") &&
87+
!preference.getName().equals(DATA_INIT_PREFERENCE_NAME)) {
88+
result.add(new PortletInstancePreference(preference.getName(), preference.getValue()));
89+
}
90+
});
91+
if (!StringUtils.isBlank(settingName)) {
92+
if (portletInstanceContext.isExport()) {
93+
//portlet is in export process
94+
//we need to put background images and translations in preferences
95+
result.addAll(computePreferencesToExport(settingName));
96+
} else {
97+
result.add(new PortletInstancePreference(DATA_INIT_PREFERENCE_NAME, settingName));
98+
}
99+
} else {
100+
101+
if (portletInstanceContext.isExport() && preferences.getPreference(DATA_INIT_PREFERENCE_NAME) != null) {
102+
//portlet is in export process
103+
//we need to put background images and translations in preferences
104+
settingName = preferences.getPreference(DATA_INIT_PREFERENCE_NAME).getValue();
105+
result.addAll(computePreferencesToExport(settingName));
106+
}
107+
}
108+
109+
110+
return result;
111+
}
112+
113+
private String getFileContent(String id) {
114+
try {
115+
FileItem
116+
file =
117+
fileService.getFile(Long.parseLong(id));
118+
if (file == null) {
119+
return null;
120+
} else {
121+
return Base64.encodeBase64String(file.getAsByte());
122+
}
123+
} catch (FileStorageException e) {
124+
LOG.warn("Unable to read file with id=", id, e);
125+
return null;
126+
}
127+
}
128+
129+
private String getCmsSettingName(Portlet preferences) {
130+
if (preferences == null) {
131+
return null;
132+
}
133+
Preference settingNamePreference = preferences.getPreference(CMS_SETTING_PREFERENCE_NAME);
134+
return settingNamePreference == null ? null : settingNamePreference.getValue();
135+
}
136+
137+
private List<PortletInstancePreference> computePreferencesToExport(String settingName) {
138+
List<PortletInstancePreference> preferencesToExport = new ArrayList<>();
139+
140+
try {
141+
JSONObject translationsJson = new JSONObject();
142+
Map<String, TranslationField>
143+
translations = translationService.getAllTranslationFields(OBJECT_TYPE, settingName);
144+
translations.entrySet().forEach(entry -> {
145+
String translationKey = entry.getKey();
146+
TranslationField translationField = entry.getValue();
147+
if (!translationField.getLabels().isEmpty()) {
148+
translationsJson.put(translationKey, translationField.getLabels());
149+
}
150+
});
151+
if (!translationsJson.isEmpty()) {
152+
preferencesToExport.add(new PortletInstancePreference(EXPORT_DATA_TRANSLATION_INIT_PREFERENCE_NAME,
153+
translationsJson.toString()));
154+
}
155+
} catch (ObjectNotFoundException o) {
156+
//nothing to do, no translations to copy
157+
}
158+
159+
ObjectAttachmentList attachmentList = attachmentService.getAttachments(OBJECT_TYPE, settingName);
160+
ObjectAttachmentDetail file = attachmentList == null || attachmentList.getAttachments() == null || attachmentList.getAttachments().size() == 0 ?
161+
null :
162+
attachmentList.getAttachments().getFirst();
163+
if (file != null) {
164+
String fileContent = getFileContent(file.getId());
165+
preferencesToExport.add(new PortletInstancePreference(EXPORT_DATA_INIT_PREFERENCE_NAME, fileContent));
166+
if (file.getAltText() != null) {
167+
preferencesToExport.add(new PortletInstancePreference(EXPORT_DATA_ALT_INIT_PREFERENCE_NAME, file.getAltText()));
168+
}
169+
}
170+
return preferencesToExport;
171+
}
172+
}

layout-service/src/main/java/io/meeds/layout/plugin/renderer/LoginFormPortletInstancePreferencePlugin.java

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,47 +21,27 @@
2121

2222
import io.meeds.layout.model.PortletInstanceContext;
2323
import io.meeds.layout.model.PortletInstancePreference;
24-
import io.meeds.layout.plugin.PortletInstancePreferencePlugin;
25-
import org.apache.commons.lang3.StringUtils;
24+
import lombok.SneakyThrows;
2625
import org.exoplatform.portal.config.model.Application;
2726
import org.exoplatform.portal.pom.spi.portlet.Portlet;
28-
import org.exoplatform.portal.pom.spi.portlet.Preference;
2927
import org.springframework.stereotype.Service;
3028

31-
import java.util.Collections;
3229
import java.util.List;
3330

3431
@Service
35-
public class LoginFormPortletInstancePreferencePlugin implements PortletInstancePreferencePlugin {
36-
37-
38-
private static final String DATA_INIT_PREFERENCE_NAME = "data.init";
39-
40-
private static final String CMS_SETTING_PREFERENCE_NAME = "name";
41-
32+
public class LoginFormPortletInstancePreferencePlugin extends CMSPortletInstancePreferencePlugin {
4233

4334
@Override
4435
public String getPortletName() {
4536
return "LoginForm";
4637
}
4738

4839
@Override
40+
@SneakyThrows
4941
public List<PortletInstancePreference> generatePreferences(Application application,
5042
Portlet preferences,
5143
PortletInstanceContext portletInstanceContext) {
52-
String settingName = getCmsSettingName(preferences);
53-
if (!StringUtils.isBlank(settingName)) {
54-
return Collections.singletonList(new PortletInstancePreference(DATA_INIT_PREFERENCE_NAME, settingName));
55-
} else {
56-
return Collections.emptyList();
57-
}
58-
}
44+
return super.generatePreferences(application, preferences, portletInstanceContext);
5945

60-
private String getCmsSettingName(Portlet preferences) {
61-
if (preferences == null) {
62-
return null;
63-
}
64-
Preference settingNamePreference = preferences.getPreference(CMS_SETTING_PREFERENCE_NAME);
65-
return settingNamePreference == null ? null : settingNamePreference.getValue();
6646
}
6747
}
Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
/**
22
* This file is part of the Meeds project (https://meeds.io/).
3-
*
43
* Copyright (C) 2020 - 2025 Meeds Association contact@meeds.io
5-
*
64
* This program is free software; you can redistribute it and/or
75
* modify it under the terms of the GNU Lesser General Public
86
* License as published by the Free Software Foundation; either
97
* version 3 of the License, or (at your option) any later version.
10-
*
118
* This program is distributed in the hope that it will be useful,
129
* but WITHOUT ANY WARRANTY; without even the implied warranty of
1310
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1411
* Lesser General Public License for more details.
15-
*
1612
* You should have received a copy of the GNU Lesser General Public License
1713
* along with this program; if not, write to the Free Software Foundation,
1814
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -21,45 +17,29 @@
2117

2218
import io.meeds.layout.model.PortletInstanceContext;
2319
import io.meeds.layout.model.PortletInstancePreference;
24-
import io.meeds.layout.plugin.PortletInstancePreferencePlugin;
25-
import org.apache.commons.lang3.StringUtils;
20+
import lombok.SneakyThrows;
2621
import org.exoplatform.portal.config.model.Application;
2722
import org.exoplatform.portal.pom.spi.portlet.Portlet;
28-
import org.exoplatform.portal.pom.spi.portlet.Preference;
2923
import org.springframework.stereotype.Service;
3024

31-
import java.util.Collections;
3225
import java.util.List;
3326

3427
@Service
35-
public class SidebarLoginPortletInstancePreferencePlugin implements PortletInstancePreferencePlugin {
36-
37-
private static final String DATA_INIT_PREFERENCE_NAME = "data.init";
38-
39-
private static final String CMS_SETTING_PREFERENCE_NAME = "name";
28+
public class SidebarLoginPortletInstancePreferencePlugin extends CMSPortletInstancePreferencePlugin {
4029

4130
@Override
4231
public String getPortletName() {
4332
return "SidebarLogin";
33+
4434
}
4535

4636
@Override
37+
@SneakyThrows
4738
public List<PortletInstancePreference> generatePreferences(Application application,
4839
Portlet preferences,
4940
PortletInstanceContext portletInstanceContext) {
50-
String settingName = getCmsSettingName(preferences);
51-
if (!StringUtils.isBlank(settingName)) {
52-
return Collections.singletonList(new PortletInstancePreference(DATA_INIT_PREFERENCE_NAME, settingName));
53-
} else {
54-
return Collections.emptyList();
55-
}
56-
}
41+
return super.generatePreferences(application, preferences, portletInstanceContext);
5742

58-
private String getCmsSettingName(Portlet preferences) {
59-
if (preferences == null) {
60-
return null;
61-
}
62-
Preference settingNamePreference = preferences.getPreference(CMS_SETTING_PREFERENCE_NAME);
63-
return settingNamePreference == null ? null : settingNamePreference.getValue();
6443
}
44+
6545
}

layout-service/src/test/java/io/meeds/layout/plugin/renderer/LoginFormPortletInstancePreferencePluginTest.java

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,32 @@
2020

2121
import io.meeds.layout.model.PortletInstanceContext;
2222
import io.meeds.layout.model.PortletInstancePreference;
23+
import io.meeds.social.translation.service.TranslationService;
24+
import lombok.SneakyThrows;
25+
import org.exoplatform.commons.file.services.FileService;
26+
import org.exoplatform.container.PortalContainer;
2327
import org.exoplatform.portal.pom.spi.portlet.Portlet;
2428
import org.exoplatform.portal.pom.spi.portlet.Preference;
29+
import org.exoplatform.social.attachment.AttachmentService;
30+
import org.junit.jupiter.api.BeforeEach;
2531
import org.junit.jupiter.api.Test;
2632
import org.junit.jupiter.api.extension.ExtendWith;
2733
import org.mockito.junit.jupiter.MockitoExtension;
2834
import org.springframework.beans.factory.annotation.Autowired;
2935
import org.springframework.boot.test.context.SpringBootTest;
36+
import org.springframework.boot.test.mock.mockito.MockBean;
3037

38+
import java.io.File;
3139
import java.util.HashMap;
3240
import java.util.List;
3341
import java.util.Map;
3442

3543
import static org.junit.Assert.assertNotNull;
3644
import static org.junit.jupiter.api.Assertions.assertEquals;
45+
import static org.mockito.ArgumentMatchers.any;
46+
import static org.mockito.Mockito.lenient;
47+
import static org.mockito.Mockito.mock;
48+
import static org.mockito.Mockito.when;
3749

3850
@SpringBootTest(classes = {
3951
LoginFormPortletInstancePreferencePlugin.class,
@@ -48,6 +60,21 @@ public class LoginFormPortletInstancePreferencePluginTest {
4860
@Autowired
4961
private LoginFormPortletInstancePreferencePlugin loginFormPortletInstancePreferencePlugin;
5062

63+
@MockBean
64+
private TranslationService translationService;
65+
66+
@MockBean
67+
private FileService fileService;
68+
69+
@MockBean
70+
private AttachmentService attachmentService;
71+
72+
@BeforeEach
73+
@SneakyThrows
74+
public void setup() {
75+
lenient().when(translationService.getAllTranslationFields(any(),any())).thenReturn(new HashMap<>());
76+
}
77+
5178
@Test
5279
void getPortletName() {
5380
assertEquals("LoginForm", loginFormPortletInstancePreferencePlugin.getPortletName());
@@ -61,8 +88,25 @@ void generatePreferences() {
6188
Portlet preferences = new Portlet(map);
6289
List<PortletInstancePreference> generatedPreferences = loginFormPortletInstancePreferencePlugin.generatePreferences(null, preferences, new PortletInstanceContext());
6390
assertNotNull(generatedPreferences);
91+
assertEquals(2, generatedPreferences.size());
92+
assertEquals(DATA_INIT_PREFERENCE_NAME, generatedPreferences.get(1).getName());
93+
}
94+
95+
@SneakyThrows
96+
@Test
97+
void generatePreferencesWithComputeForExport() {
98+
Map<String, Preference> map = new HashMap<>();
99+
map.put(SETTING_NAME, new Preference(SETTING_NAME, "value", false));
100+
map.put(OTHER_PREF_NAME, new Preference(OTHER_PREF_NAME, "value", false));
101+
102+
PortletInstanceContext portletInstanceContext = mock(PortletInstanceContext.class);
103+
when(portletInstanceContext.isExport()).thenReturn(true);
104+
105+
Portlet preferences = new Portlet(map);
106+
List<PortletInstancePreference> generatedPreferences = loginFormPortletInstancePreferencePlugin.generatePreferences(null, preferences, portletInstanceContext);
107+
assertNotNull(generatedPreferences);
64108
assertEquals(1, generatedPreferences.size());
65-
assertEquals(DATA_INIT_PREFERENCE_NAME, generatedPreferences.get(0).getName());
109+
assertEquals("name2", generatedPreferences.get(0).getName());
66110
}
67111

68112
}

0 commit comments

Comments
 (0)