001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.blogs.lar;
016    
017    import com.liferay.portal.kernel.lar.BasePortletDataHandler;
018    import com.liferay.portal.kernel.lar.PortletDataContext;
019    import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
020    import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
021    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
022    import com.liferay.portal.kernel.util.StreamUtil;
023    import com.liferay.portal.kernel.util.StringBundler;
024    import com.liferay.portal.kernel.util.StringPool;
025    import com.liferay.portal.kernel.util.StringUtil;
026    import com.liferay.portal.kernel.util.Validator;
027    import com.liferay.portal.kernel.workflow.WorkflowConstants;
028    import com.liferay.portal.kernel.xml.Document;
029    import com.liferay.portal.kernel.xml.Element;
030    import com.liferay.portal.kernel.xml.SAXReaderUtil;
031    import com.liferay.portal.model.Image;
032    import com.liferay.portal.service.ServiceContext;
033    import com.liferay.portal.service.persistence.ImageUtil;
034    import com.liferay.portal.util.PortletKeys;
035    import com.liferay.portal.util.PropsValues;
036    import com.liferay.portlet.blogs.model.BlogsEntry;
037    import com.liferay.portlet.blogs.service.BlogsEntryLocalServiceUtil;
038    import com.liferay.portlet.blogs.service.persistence.BlogsEntryUtil;
039    import com.liferay.portlet.journal.lar.JournalPortletDataHandlerImpl;
040    
041    import java.io.InputStream;
042    
043    import java.util.Calendar;
044    import java.util.List;
045    
046    import javax.portlet.PortletPreferences;
047    
048    /**
049     * @author Bruno Farache
050     * @author Raymond Augé
051     * @author Juan Fernández
052     */
053    public class BlogsPortletDataHandlerImpl extends BasePortletDataHandler {
054    
055            @Override
056            public PortletDataHandlerControl[] getExportControls() {
057                    return new PortletDataHandlerControl[] {
058                            _entries, _categories, _comments, _ratings, _tags
059                    };
060            }
061    
062            @Override
063            public PortletDataHandlerControl[] getImportControls() {
064                    return new PortletDataHandlerControl[] {
065                            _entries, _categories, _comments, _ratings, _tags, _wordpress
066                    };
067            }
068    
069            @Override
070            public boolean isAlwaysExportable() {
071                    return _ALWAYS_EXPORTABLE;
072            }
073    
074            @Override
075            public boolean isPublishToLiveByDefault() {
076                    return PropsValues.BLOGS_PUBLISH_TO_LIVE_BY_DEFAULT;
077            }
078    
079            @Override
080            protected PortletPreferences doDeleteData(
081                            PortletDataContext portletDataContext, String portletId,
082                            PortletPreferences portletPreferences)
083                    throws Exception {
084    
085                    if (!portletDataContext.addPrimaryKey(
086                                    BlogsPortletDataHandlerImpl.class, "deleteData")) {
087    
088                            BlogsEntryLocalServiceUtil.deleteEntries(
089                                    portletDataContext.getScopeGroupId());
090                    }
091    
092                    return null;
093            }
094    
095            @Override
096            protected String doExportData(
097                            PortletDataContext portletDataContext, String portletId,
098                            PortletPreferences portletPreferences)
099                    throws Exception {
100    
101                    portletDataContext.addPermissions(
102                            "com.liferay.portlet.blogs", portletDataContext.getScopeGroupId());
103    
104                    Document document = SAXReaderUtil.createDocument();
105    
106                    Element rootElement = document.addElement("blogs-data");
107    
108                    rootElement.addAttribute(
109                            "group-id", String.valueOf(portletDataContext.getScopeGroupId()));
110    
111                    Element entriesElement = rootElement.addElement("entries");
112    
113                    Element dlFileEntryTypesElement = entriesElement.addElement(
114                            "dl-file-entry-types");
115                    Element dlFoldersElement = entriesElement.addElement("dl-folders");
116                    Element dlFileEntriesElement = entriesElement.addElement(
117                            "dl-file-entries");
118                    Element dlFileRanksElement = entriesElement.addElement("dl-file-ranks");
119    
120                    List<BlogsEntry> entries = BlogsEntryUtil.findByGroupId(
121                            portletDataContext.getScopeGroupId());
122    
123                    for (BlogsEntry entry : entries) {
124                            exportEntry(
125                                    portletDataContext, entriesElement, dlFileEntryTypesElement,
126                                    dlFoldersElement, dlFileEntriesElement, dlFileRanksElement,
127                                    entry);
128                    }
129    
130                    return document.formattedString();
131            }
132    
133            @Override
134            protected PortletPreferences doImportData(
135                            PortletDataContext portletDataContext, String portletId,
136                            PortletPreferences portletPreferences, String data)
137                    throws Exception {
138    
139                    portletDataContext.importPermissions(
140                            "com.liferay.portlet.blogs", portletDataContext.getSourceGroupId(),
141                            portletDataContext.getScopeGroupId());
142    
143                    Document document = SAXReaderUtil.read(data);
144    
145                    Element rootElement = document.getRootElement();
146    
147                    Element entriesElement = rootElement.element("entries");
148    
149                    if (entriesElement != null) {
150                            JournalPortletDataHandlerImpl.importReferencedData(
151                                    portletDataContext, entriesElement);
152                    }
153                    else {
154                            entriesElement = rootElement;
155                    }
156    
157                    for (Element entryElement : entriesElement.elements("entry")) {
158                            String path = entryElement.attributeValue("path");
159    
160                            if (!portletDataContext.isPathNotProcessed(path)) {
161                                    continue;
162                            }
163    
164                            BlogsEntry entry =
165                                    (BlogsEntry)portletDataContext.getZipEntryAsObject(path);
166    
167                            importEntry(portletDataContext, entryElement, entry);
168                    }
169    
170                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "wordpress")) {
171                            WordPressImporter.importData(portletDataContext);
172                    }
173    
174                    return null;
175            }
176    
177            protected void exportEntry(
178                            PortletDataContext portletDataContext, Element entriesElement,
179                            Element dlFileEntryTypesElement, Element dlFoldersElement,
180                            Element dlFileEntriesElement, Element dlFileRanksElement,
181                            BlogsEntry entry)
182                    throws Exception {
183    
184                    if (!portletDataContext.isWithinDateRange(entry.getModifiedDate())) {
185                            return;
186                    }
187    
188                    if (entry.getStatus() != WorkflowConstants.STATUS_APPROVED) {
189                            return;
190                    }
191    
192                    String path = getEntryPath(portletDataContext, entry);
193    
194                    if (!portletDataContext.isPathNotProcessed(path)) {
195                            return;
196                    }
197    
198                    // Clone this entry to make sure changes to its content are never
199                    // persisted
200    
201                    entry = (BlogsEntry)entry.clone();
202    
203                    Element entryElement = (Element)entriesElement.selectSingleNode(
204                            "//page[@path='".concat(path).concat("']"));
205    
206                    if (entryElement == null) {
207                            entryElement = entriesElement.addElement("entry");
208                    }
209    
210                    String content = JournalPortletDataHandlerImpl.exportReferencedContent(
211                            portletDataContext, dlFileEntryTypesElement, dlFoldersElement,
212                            dlFileEntriesElement, dlFileRanksElement, entryElement,
213                            entry.getContent());
214    
215                    entry.setContent(content);
216    
217                    String imagePath = getEntryImagePath(portletDataContext, entry);
218    
219                    entryElement.addAttribute("image-path", imagePath);
220    
221                    Image smallImage = ImageUtil.fetchByPrimaryKey(entry.getSmallImageId());
222    
223                    if (entry.isSmallImage() && (smallImage != null)) {
224                            String smallImagePath = getEntrySmallImagePath(
225                                    portletDataContext, entry);
226    
227                            entryElement.addAttribute("small-image-path", smallImagePath);
228    
229                            entry.setSmallImageType(smallImage.getType());
230    
231                            portletDataContext.addZipEntry(
232                                    smallImagePath, smallImage.getTextObj());
233                    }
234    
235                    portletDataContext.addClassedModel(
236                            entryElement, path, entry, _NAMESPACE);
237            }
238    
239            protected String getEntryImagePath(
240                            PortletDataContext portletDataContext, BlogsEntry entry)
241                    throws Exception {
242    
243                    StringBundler sb = new StringBundler(4);
244    
245                    sb.append(portletDataContext.getPortletPath(PortletKeys.BLOGS));
246                    sb.append("/entry/");
247                    sb.append(entry.getUuid());
248                    sb.append(StringPool.SLASH);
249    
250                    return sb.toString();
251            }
252    
253            protected String getEntryPath(
254                    PortletDataContext portletDataContext, BlogsEntry entry) {
255    
256                    StringBundler sb = new StringBundler(4);
257    
258                    sb.append(portletDataContext.getPortletPath(PortletKeys.BLOGS));
259                    sb.append("/entries/");
260                    sb.append(entry.getEntryId());
261                    sb.append(".xml");
262    
263                    return sb.toString();
264            }
265    
266            protected String getEntrySmallImagePath(
267                            PortletDataContext portletDataContext, BlogsEntry entry)
268                    throws Exception {
269    
270                    StringBundler sb = new StringBundler(6);
271    
272                    sb.append(portletDataContext.getPortletPath(PortletKeys.BLOGS));
273                    sb.append("/entries/");
274                    sb.append(entry.getUuid());
275                    sb.append("/thumbnail");
276                    sb.append(StringPool.PERIOD);
277                    sb.append(entry.getSmallImageType());
278    
279                    return sb.toString();
280            }
281    
282            protected void importEntry(
283                            PortletDataContext portletDataContext, Element entryElement,
284                            BlogsEntry entry)
285                    throws Exception {
286    
287                    long userId = portletDataContext.getUserId(entry.getUserUuid());
288    
289                    String content = JournalPortletDataHandlerImpl.importReferencedContent(
290                            portletDataContext, entryElement, entry.getContent());
291    
292                    entry.setContent(content);
293    
294                    Calendar displayDateCal = CalendarFactoryUtil.getCalendar();
295    
296                    displayDateCal.setTime(entry.getDisplayDate());
297    
298                    int displayDateMonth = displayDateCal.get(Calendar.MONTH);
299                    int displayDateDay = displayDateCal.get(Calendar.DATE);
300                    int displayDateYear = displayDateCal.get(Calendar.YEAR);
301                    int displayDateHour = displayDateCal.get(Calendar.HOUR);
302                    int displayDateMinute = displayDateCal.get(Calendar.MINUTE);
303    
304                    if (displayDateCal.get(Calendar.AM_PM) == Calendar.PM) {
305                            displayDateHour += 12;
306                    }
307    
308                    boolean allowPingbacks = entry.isAllowPingbacks();
309                    boolean allowTrackbacks = entry.isAllowTrackbacks();
310                    String[] trackbacks = StringUtil.split(entry.getTrackbacks());
311                    int status = entry.getStatus();
312    
313                    ServiceContext serviceContext = portletDataContext.createServiceContext(
314                            entryElement, entry, _NAMESPACE);
315    
316                    if (status != WorkflowConstants.STATUS_APPROVED) {
317                            serviceContext.setWorkflowAction(
318                                    WorkflowConstants.ACTION_SAVE_DRAFT);
319                    }
320    
321                    String smallImageFileName = null;
322                    InputStream smallImageInputStream = null;
323    
324                    try {
325                            String smallImagePath = entryElement.attributeValue(
326                                    "small-image-path");
327    
328                            if (entry.isSmallImage() && Validator.isNotNull(smallImagePath)) {
329                                    smallImageFileName =
330                                            String.valueOf(entry.getSmallImageId()).concat(
331                                                    StringPool.PERIOD).concat(entry.getSmallImageType());
332                                    smallImageInputStream =
333                                            portletDataContext.getZipEntryAsInputStream(smallImagePath);
334                            }
335    
336                            BlogsEntry importedEntry = null;
337    
338                            if (portletDataContext.isDataStrategyMirror()) {
339                                    BlogsEntry existingEntry = BlogsEntryUtil.fetchByUUID_G(
340                                            entry.getUuid(), portletDataContext.getScopeGroupId());
341    
342                                    if (existingEntry == null) {
343                                            serviceContext.setUuid(entry.getUuid());
344    
345                                            importedEntry = BlogsEntryLocalServiceUtil.addEntry(
346                                                    userId, entry.getTitle(), entry.getDescription(),
347                                                    entry.getContent(), displayDateMonth, displayDateDay,
348                                                    displayDateYear, displayDateHour, displayDateMinute,
349                                                    allowPingbacks, allowTrackbacks, trackbacks,
350                                                    entry.isSmallImage(), entry.getSmallImageURL(),
351                                                    smallImageFileName, smallImageInputStream,
352                                                    serviceContext);
353                                    }
354                                    else {
355                                            importedEntry = BlogsEntryLocalServiceUtil.updateEntry(
356                                                    userId, existingEntry.getEntryId(), entry.getTitle(),
357                                                    entry.getDescription(), entry.getContent(),
358                                                    displayDateMonth, displayDateDay, displayDateYear,
359                                                    displayDateHour, displayDateMinute, allowPingbacks,
360                                                    allowTrackbacks, trackbacks, entry.getSmallImage(),
361                                                    entry.getSmallImageURL(), smallImageFileName,
362                                                    smallImageInputStream, serviceContext);
363                                    }
364                            }
365                            else {
366                                    importedEntry = BlogsEntryLocalServiceUtil.addEntry(
367                                            userId, entry.getTitle(), entry.getDescription(),
368                                            entry.getContent(), displayDateMonth, displayDateDay,
369                                            displayDateYear, displayDateHour, displayDateMinute,
370                                            allowPingbacks, allowTrackbacks, trackbacks,
371                                            entry.getSmallImage(), entry.getSmallImageURL(),
372                                            smallImageFileName, smallImageInputStream,
373                                            serviceContext);
374                            }
375    
376                            portletDataContext.importClassedModel(
377                                    entry, importedEntry, _NAMESPACE);
378                    }
379                    finally {
380                            StreamUtil.cleanUp(smallImageInputStream);
381                    }
382    
383            }
384    
385            private static final boolean _ALWAYS_EXPORTABLE = true;
386    
387            private static final String _NAMESPACE = "blogs";
388    
389            private static PortletDataHandlerBoolean _categories =
390                    new PortletDataHandlerBoolean(_NAMESPACE, "categories");
391    
392            private static PortletDataHandlerBoolean _comments =
393                    new PortletDataHandlerBoolean(_NAMESPACE, "comments");
394    
395            private static PortletDataHandlerBoolean _entries =
396                    new PortletDataHandlerBoolean(_NAMESPACE, "entries", true, true);
397    
398            private static PortletDataHandlerBoolean _ratings =
399                    new PortletDataHandlerBoolean(_NAMESPACE, "ratings");
400    
401            private static PortletDataHandlerBoolean _tags =
402                    new PortletDataHandlerBoolean(_NAMESPACE, "tags");
403    
404            private static PortletDataHandlerBoolean _wordpress =
405                    new PortletDataHandlerBoolean(_NAMESPACE, "wordpress");
406    
407    }