1
14
15 package com.liferay.portlet.blogs.lar;
16
17 import com.liferay.portal.kernel.exception.PortalException;
18 import com.liferay.portal.kernel.exception.SystemException;
19 import com.liferay.portal.kernel.log.Log;
20 import com.liferay.portal.kernel.log.LogFactoryUtil;
21 import com.liferay.portal.kernel.util.DateFormatFactoryUtil;
22 import com.liferay.portal.kernel.util.GetterUtil;
23 import com.liferay.portal.kernel.util.StringPool;
24 import com.liferay.portal.kernel.util.Validator;
25 import com.liferay.portal.kernel.workflow.StatusConstants;
26 import com.liferay.portal.kernel.xml.Document;
27 import com.liferay.portal.kernel.xml.DocumentException;
28 import com.liferay.portal.kernel.xml.Element;
29 import com.liferay.portal.kernel.xml.Namespace;
30 import com.liferay.portal.kernel.xml.Node;
31 import com.liferay.portal.kernel.xml.SAXReaderUtil;
32 import com.liferay.portal.lar.PortletDataContext;
33 import com.liferay.portal.model.User;
34 import com.liferay.portal.service.ServiceContext;
35 import com.liferay.portal.service.UserLocalServiceUtil;
36 import com.liferay.portal.service.persistence.UserUtil;
37 import com.liferay.portal.util.PortletKeys;
38 import com.liferay.portlet.blogs.model.BlogsEntry;
39 import com.liferay.portlet.blogs.service.BlogsEntryLocalServiceUtil;
40 import com.liferay.portlet.messageboards.model.MBMessage;
41 import com.liferay.portlet.messageboards.model.MBMessageDisplay;
42 import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
43
44 import java.text.DateFormat;
45 import java.text.ParseException;
46
47 import java.util.Calendar;
48 import java.util.Date;
49 import java.util.HashMap;
50 import java.util.List;
51 import java.util.Map;
52 import java.util.TimeZone;
53
54
59 public class WordPressImporter {
60
61 public static void importData(PortletDataContext context)
62 throws PortalException, SystemException {
63
64 Map<String, Long> userMap = getWordPressUserMap(context);
65
66 String path = getWordPressPath(context, _EXPORT_FILE);
67
68 String fileData = context.getZipEntryAsString(path);
69
70 if (Validator.isNull(fileData)) {
71 return;
72 }
73
74 Document wordPressDoc = null;
75
76 try {
77 wordPressDoc = SAXReaderUtil.read(fileData);
78 }
79 catch (DocumentException de) {
80 _log.error("Reading " + path, de);
81
82 return;
83 }
84
85 User defaultUser = UserLocalServiceUtil.getDefaultUser(
86 context.getCompanyId());
87
88 Element root = wordPressDoc.getRootElement();
89
90 List<Element> entryEls = root.element("channel").elements("item");
91
92 DateFormat dateFormat = DateFormatFactoryUtil.getSimpleDateFormat(
93 _DATE_FORMAT);
94
95 dateFormat.setTimeZone(TimeZone.getTimeZone(StringPool.UTC));
96
97 for (Element entryEl : entryEls) {
98 importEntry(context, defaultUser, userMap, dateFormat, entryEl);
99 }
100 }
101
102 protected static String getWordPressPath(
103 PortletDataContext context, String fileName) {
104
105 return context.getSourcePortletPath(PortletKeys.BLOGS).concat(
106 StringPool.SLASH).concat(fileName);
107 }
108
109 protected static Map<String, Long> getWordPressUserMap(
110 PortletDataContext context) {
111
112 Map<String, Long> userMap = new HashMap<String, Long>();
113
114 String path = getWordPressPath(context, _USER_MAP_FILE);
115
116 String fileData = context.getZipEntryAsString(path);
117
118 if (Validator.isNull(fileData)) {
119 return userMap;
120 }
121
122 Document doc = null;
123
124 try {
125 doc = SAXReaderUtil.read(fileData);
126 }
127 catch(DocumentException de) {
128 _log.error(de.getMessage(), de);
129
130 return userMap;
131 }
132
133 Element root = doc.getRootElement();
134
135 List<Element> userEls = root.elements("wordpress-user");
136
137 for (Element userEl : userEls) {
138 try {
139 User user = UserUtil.findByC_EA(
140 context.getCompanyId(),
141 userEl.attributeValue("email-address"));
142
143 userMap.put(userEl.getTextTrim(), user.getUserId());
144 }
145 catch (Exception e) {
146 if (_log.isDebugEnabled()) {
147 _log.debug(
148 "User for {" + context.getCompanyId() + ", " +
149 userEl.attributeValue("email-address") + "}", e);
150 }
151 }
152 }
153
154 return userMap;
155 }
156
157 protected static void importComment(
158 PortletDataContext context, User defaultUser,
159 MBMessageDisplay messageDisplay, Map<Long, Long> messageIdMap,
160 BlogsEntry entry, Element commentEl)
161 throws PortalException, SystemException {
162
163 long commentId = GetterUtil.getLong(
164 commentEl.elementTextTrim(
165 SAXReaderUtil.createQName("comment_id", _NS_WP)));
166
167 String commentContent = commentEl.elementTextTrim(
168 SAXReaderUtil.createQName("comment_content", _NS_WP));
169
170 if (Validator.isNull(commentContent)) {
171 return;
172 }
173
174 String commentAuthor = commentEl.elementTextTrim(
175 SAXReaderUtil.createQName("comment_author", _NS_WP));
176
177 commentAuthor = commentAuthor.substring(
178 0, Math.min(75, commentAuthor.length()));
179
180 long commentParentId = GetterUtil.getLong(
181 commentEl.elementTextTrim(
182 SAXReaderUtil.createQName("comment_parent", _NS_WP)));
183
184 if (commentParentId == 0) {
185 commentParentId =
186 messageDisplay.getMessage().getMessageId();
187 }
188 else {
189 commentParentId = messageIdMap.get(commentParentId);
190 }
191
192 ServiceContext serviceContext = new ServiceContext();
193
194 serviceContext.setAddCommunityPermissions(true);
195 serviceContext.setAddGuestPermissions(true);
196 serviceContext.setScopeGroupId(context.getGroupId());
197
198 MBMessage message = MBMessageLocalServiceUtil.addDiscussionMessage(
199 defaultUser.getUserId(), commentAuthor, BlogsEntry.class.getName(),
200 entry.getEntryId(), messageDisplay.getThread().getThreadId(),
201 commentParentId, null, commentContent, serviceContext);
202
203 messageIdMap.put(commentId, message.getMessageId());
204 }
205
206 protected static void importEntry(
207 PortletDataContext context, User defaultUser,
208 Map<String, Long> userMap, DateFormat dateFormat, Element entryEl)
209 throws PortalException, SystemException {
210
211 long userId = context.getUserId(null);
212
213 String creator = entryEl.elementText(
214 SAXReaderUtil.createQName("creator", _NS_DC));
215
216 if (userMap.containsKey(creator)) {
217 userId = userMap.get(creator);
218 }
219
220 String title = entryEl.elementTextTrim("title");
221
222 if (Validator.isNull(title)) {
223 title = entryEl.elementTextTrim(
224 SAXReaderUtil.createQName("post_name", _NS_WP));
225 }
226
227 String content = entryEl.elementText(
228 SAXReaderUtil.createQName("encoded", _NS_CONTENT));
229
230 content = content.replaceAll("\\n", "\n<br />");
231
232
234 if (Validator.isNull(content)) {
235 content = "<br />";
236 }
237
238 String dateText = entryEl.elementTextTrim(
239 SAXReaderUtil.createQName("post_date_gmt", _NS_WP));
240
241 Date postDate = new Date();
242
243 try {
244 postDate = dateFormat.parse(dateText);
245 }
246 catch (ParseException pe) {
247 _log.warn("Parse " + dateText, pe);
248 }
249
250 Calendar cal = Calendar.getInstance();
251
252 cal.setTime(postDate);
253
254 int displayDateMonth = cal.get(Calendar.MONTH);
255 int displayDateDay = cal.get(Calendar.DAY_OF_MONTH);
256 int displayDateYear = cal.get(Calendar.YEAR);
257 int displayDateHour = cal.get(Calendar.HOUR_OF_DAY);
258 int displayDateMinute = cal.get(Calendar.MINUTE);
259
260 String statusText = entryEl.elementTextTrim(
261 SAXReaderUtil.createQName("status", _NS_WP));
262
263 int status = StatusConstants.APPROVED;
264
265 if (statusText.equalsIgnoreCase("draft")) {
266 status = StatusConstants.DRAFT;
267 }
268
269 String pingStatusText = entryEl.elementTextTrim(
270 SAXReaderUtil.createQName("ping_status", _NS_WP));
271
272 boolean allowPingbacks = pingStatusText.equalsIgnoreCase("open");
273 boolean allowTrackbacks = allowPingbacks;
274
275 String[] assetTagNames = null;
276
277 String categoryText = entryEl.elementTextTrim("category");
278
279 if (Validator.isNotNull(categoryText)) {
280 assetTagNames = new String[] {categoryText};
281 }
282
283 ServiceContext serviceContext = new ServiceContext();
284
285 serviceContext.setAddCommunityPermissions(true);
286 serviceContext.setAddGuestPermissions(true);
287 serviceContext.setAssetTagNames(assetTagNames);
288 serviceContext.setScopeGroupId(context.getGroupId());
289 serviceContext.setStatus(status);
290
291 BlogsEntry entry = null;
292
293 try {
294 entry = BlogsEntryLocalServiceUtil.addEntry(
295 null, userId, title, content, displayDateMonth, displayDateDay,
296 displayDateYear, displayDateHour, displayDateMinute,
297 allowPingbacks, allowTrackbacks, null, serviceContext);
298 }
299 catch (Exception e) {
300 _log.error("Add entry " + title, e);
301
302 return;
303 }
304
305 MBMessageDisplay messageDisplay =
306 MBMessageLocalServiceUtil.getDiscussionMessageDisplay(
307 userId, BlogsEntry.class.getName(), entry.getEntryId(),
308 StatusConstants.APPROVED);
309
310 Map<Long, Long> messageIdMap = new HashMap<Long, Long>();
311
312 List<Node> commentNodes = entryEl.selectNodes(
313 "wp:comment", "wp:comment_parent/text()");
314
315 for (Node commentNode : commentNodes) {
316 Element commentEl = (Element)commentNode;
317
318 importComment(
319 context, defaultUser, messageDisplay, messageIdMap, entry,
320 commentEl);
321 }
322 }
323
324 private static final String _DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
325
326 private static final String _EXPORT_FILE = "wordpress.xml";
327
328 private static final Namespace _NS_CONTENT = SAXReaderUtil.createNamespace(
329 "content", "http://purl.org/rss/1.0/modules/content/");
330
331 private static final Namespace _NS_DC = SAXReaderUtil.createNamespace(
332 "dc", "http://purl.org/dc/elements/1.1/");
333
334 private static final Namespace _NS_WP = SAXReaderUtil.createNamespace(
335 "wp", "http://wordpress.org/export/1.0/");
336
337 private static final String _USER_MAP_FILE = "wordpress-user-map.xml";
338
339 private static Log _log = LogFactoryUtil.getLog(WordPressImporter.class);
340
341 }