001    /**
002     * Copyright (c) 2000-2013 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.ExportImportPathUtil;
019    import com.liferay.portal.kernel.lar.PortletDataContext;
020    import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
021    import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
022    import com.liferay.portal.kernel.util.CalendarFactoryUtil;
023    import com.liferay.portal.kernel.util.StreamUtil;
024    import com.liferay.portal.kernel.util.StringBundler;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.kernel.util.StringUtil;
027    import com.liferay.portal.kernel.util.Validator;
028    import com.liferay.portal.kernel.workflow.WorkflowConstants;
029    import com.liferay.portal.kernel.xml.Element;
030    import com.liferay.portal.model.Image;
031    import com.liferay.portal.service.ServiceContext;
032    import com.liferay.portal.service.persistence.ImageUtil;
033    import com.liferay.portal.util.PortletKeys;
034    import com.liferay.portal.util.PropsValues;
035    import com.liferay.portlet.blogs.model.BlogsEntry;
036    import com.liferay.portlet.blogs.service.BlogsEntryLocalServiceUtil;
037    import com.liferay.portlet.blogs.service.BlogsStatsUserLocalServiceUtil;
038    import com.liferay.portlet.blogs.service.persistence.BlogsEntryUtil;
039    import com.liferay.portlet.dynamicdatamapping.lar.DDMPortletDataHandler;
040    import com.liferay.portlet.journal.lar.JournalPortletDataHandler;
041    
042    import java.io.InputStream;
043    
044    import java.util.Calendar;
045    import java.util.List;
046    
047    import javax.portlet.PortletPreferences;
048    
049    /**
050     * @author Bruno Farache
051     * @author Raymond Augé
052     * @author Juan Fernández
053     */
054    public class BlogsPortletDataHandler extends BasePortletDataHandler {
055    
056            public static final String NAMESPACE = "blogs";
057    
058            public BlogsPortletDataHandler() {
059                    setAlwaysExportable(true);
060                    setExportControls(
061                            new PortletDataHandlerBoolean(NAMESPACE, "entries", true, true));
062                    setExportMetadataControls(
063                            new PortletDataHandlerBoolean(
064                                    NAMESPACE, "blog-entries", true,
065                                    new PortletDataHandlerControl[] {
066                                            new PortletDataHandlerBoolean(NAMESPACE, "categories"),
067                                            new PortletDataHandlerBoolean(NAMESPACE, "comments"),
068                                            new PortletDataHandlerBoolean(NAMESPACE, "ratings"),
069                                            new PortletDataHandlerBoolean(NAMESPACE, "tags")
070                                    }));
071                    setImportMetadataControls(
072                            getExportMetadataControls()[0],
073                            new PortletDataHandlerBoolean(NAMESPACE, "wordpress"));
074                    setPublishToLiveByDefault(PropsValues.BLOGS_PUBLISH_TO_LIVE_BY_DEFAULT);
075            }
076    
077            @Override
078            protected PortletPreferences doDeleteData(
079                            PortletDataContext portletDataContext, String portletId,
080                            PortletPreferences portletPreferences)
081                    throws Exception {
082    
083                    if (portletDataContext.addPrimaryKey(
084                                    BlogsPortletDataHandler.class, "deleteData")) {
085    
086                            return portletPreferences;
087                    }
088    
089                    BlogsEntryLocalServiceUtil.deleteEntries(
090                            portletDataContext.getScopeGroupId());
091    
092                    BlogsStatsUserLocalServiceUtil.deleteStatsUserByGroupId(
093                            portletDataContext.getScopeGroupId());
094    
095                    return portletPreferences;
096            }
097    
098            @Override
099            protected String doExportData(
100                            PortletDataContext portletDataContext, String portletId,
101                            PortletPreferences portletPreferences)
102                    throws Exception {
103    
104                    portletDataContext.addPermissions(
105                            "com.liferay.portlet.blogs", portletDataContext.getScopeGroupId());
106    
107                    Element rootElement = addExportDataRootElement(portletDataContext);
108    
109                    rootElement.addAttribute(
110                            "group-id", String.valueOf(portletDataContext.getScopeGroupId()));
111    
112                    Element entriesElement = rootElement.addElement("entries");
113    
114                    Element dlFileEntryTypesElement = entriesElement.addElement(
115                            "dl-file-entry-types");
116                    Element dlFoldersElement = entriesElement.addElement("dl-folders");
117                    Element dlFileEntriesElement = entriesElement.addElement(
118                            "dl-file-entries");
119                    Element dlFileRanksElement = entriesElement.addElement("dl-file-ranks");
120                    Element dlRepositoriesElement = entriesElement.addElement(
121                            "dl-repositories");
122                    Element dlRepositoryEntriesElement = entriesElement.addElement(
123                            "dl-repository-entries");
124    
125                    List<BlogsEntry> entries = BlogsEntryUtil.findByGroupId(
126                            portletDataContext.getScopeGroupId());
127    
128                    for (BlogsEntry entry : entries) {
129                            exportEntry(
130                                    portletDataContext, entriesElement, dlFileEntryTypesElement,
131                                    dlFoldersElement, dlFileEntriesElement, dlFileRanksElement,
132                                    dlRepositoriesElement, dlRepositoryEntriesElement, entry);
133                    }
134    
135                    return getExportDataRootElementString(rootElement);
136            }
137    
138            @Override
139            protected PortletPreferences doImportData(
140                            PortletDataContext portletDataContext, String portletId,
141                            PortletPreferences portletPreferences, String data)
142                    throws Exception {
143    
144                    portletDataContext.importPermissions(
145                            "com.liferay.portlet.blogs", portletDataContext.getSourceGroupId(),
146                            portletDataContext.getScopeGroupId());
147    
148                    Element rootElement = portletDataContext.getImportDataRootElement();
149    
150                    Element entriesElement = rootElement.element("entries");
151    
152                    if (entriesElement != null) {
153                            JournalPortletDataHandler.importReferencedData(
154                                    portletDataContext, entriesElement);
155                    }
156                    else {
157                            entriesElement = rootElement;
158                    }
159    
160                    for (Element entryElement : entriesElement.elements("entry")) {
161                            String path = entryElement.attributeValue("path");
162    
163                            if (!portletDataContext.isPathNotProcessed(path)) {
164                                    continue;
165                            }
166    
167                            BlogsEntry entry =
168                                    (BlogsEntry)portletDataContext.getZipEntryAsObject(path);
169    
170                            importEntry(portletDataContext, entryElement, entry);
171                    }
172    
173                    if (portletDataContext.getBooleanParameter(NAMESPACE, "wordpress")) {
174                            WordPressImporter.importData(portletDataContext);
175                    }
176    
177                    return null;
178            }
179    
180            protected void exportEntry(
181                            PortletDataContext portletDataContext, Element entriesElement,
182                            Element dlFileEntryTypesElement, Element dlFoldersElement,
183                            Element dlFileEntriesElement, Element dlFileRanksElement,
184                            Element dlRepositoriesElement, Element dlRepositoryEntriesElement,
185                            BlogsEntry entry)
186                    throws Exception {
187    
188                    if (!portletDataContext.isWithinDateRange(entry.getModifiedDate())) {
189                            return;
190                    }
191    
192                    if (!entry.isApproved() && !entry.isInTrash()) {
193                            return;
194                    }
195    
196                    String path = getEntryPath(portletDataContext, entry);
197    
198                    if (!portletDataContext.isPathNotProcessed(path)) {
199                            return;
200                    }
201    
202                    // Clone this entry to make sure changes to its content are never
203                    // persisted
204    
205                    entry = (BlogsEntry)entry.clone();
206    
207                    Element entryElement = (Element)entriesElement.selectSingleNode(
208                            "//page[@path='".concat(path).concat("']"));
209    
210                    if (entryElement == null) {
211                            entryElement = entriesElement.addElement("entry");
212                    }
213    
214                    String content = DDMPortletDataHandler.exportReferencedContent(
215                            portletDataContext, dlFileEntryTypesElement, dlFoldersElement,
216                            dlFileEntriesElement, dlFileRanksElement, dlRepositoriesElement,
217                            dlRepositoryEntriesElement, entryElement, entry.getContent());
218    
219                    entry.setContent(content);
220    
221                    String imagePath = getEntryImagePath(portletDataContext, entry);
222    
223                    entryElement.addAttribute("image-path", imagePath);
224    
225                    if (entry.isSmallImage()) {
226                            Image smallImage = ImageUtil.fetchByPrimaryKey(
227                                    entry.getSmallImageId());
228    
229                            if (Validator.isNotNull(entry.getSmallImageURL())) {
230                                    String smallImageURL =
231                                            DDMPortletDataHandler.exportReferencedContent(
232                                                    portletDataContext, dlFileEntryTypesElement,
233                                                    dlFoldersElement, dlFileEntriesElement,
234                                                    dlFileRanksElement, dlRepositoriesElement,
235                                                    dlRepositoryEntriesElement, entryElement,
236                                                    entry.getSmallImageURL().concat(StringPool.SPACE));
237    
238                                    entry.setSmallImageURL(smallImageURL);
239                            }
240                            else if (smallImage != null) {
241                                    String smallImagePath = getEntrySmallImagePath(
242                                            portletDataContext, entry);
243    
244                                    entryElement.addAttribute("small-image-path", smallImagePath);
245    
246                                    entry.setSmallImageType(smallImage.getType());
247    
248                                    portletDataContext.addZipEntry(
249                                            smallImagePath, smallImage.getTextObj());
250                            }
251                    }
252    
253                    portletDataContext.addClassedModel(
254                            entryElement, path, entry, NAMESPACE);
255            }
256    
257            protected String getEntryImagePath(
258                            PortletDataContext portletDataContext, BlogsEntry entry)
259                    throws Exception {
260    
261                    StringBundler sb = new StringBundler(4);
262    
263                    sb.append(
264                            ExportImportPathUtil.getPortletPath(
265                                    portletDataContext, PortletKeys.BLOGS));
266                    sb.append("/entry/");
267                    sb.append(entry.getUuid());
268                    sb.append(StringPool.SLASH);
269    
270                    return sb.toString();
271            }
272    
273            protected String getEntryPath(
274                    PortletDataContext portletDataContext, BlogsEntry entry) {
275    
276                    StringBundler sb = new StringBundler(4);
277    
278                    sb.append(
279                            ExportImportPathUtil.getPortletPath(
280                                    portletDataContext, PortletKeys.BLOGS));
281                    sb.append("/entries/");
282                    sb.append(entry.getEntryId());
283                    sb.append(".xml");
284    
285                    return sb.toString();
286            }
287    
288            protected String getEntrySmallImagePath(
289                            PortletDataContext portletDataContext, BlogsEntry entry)
290                    throws Exception {
291    
292                    StringBundler sb = new StringBundler(6);
293    
294                    sb.append(
295                            ExportImportPathUtil.getPortletPath(
296                                    portletDataContext, PortletKeys.BLOGS));
297                    sb.append("/entries/");
298                    sb.append(entry.getUuid());
299                    sb.append("/thumbnail");
300                    sb.append(StringPool.PERIOD);
301                    sb.append(entry.getSmallImageType());
302    
303                    return sb.toString();
304            }
305    
306            protected void importEntry(
307                            PortletDataContext portletDataContext, Element entryElement,
308                            BlogsEntry entry)
309                    throws Exception {
310    
311                    long userId = portletDataContext.getUserId(entry.getUserUuid());
312    
313                    String content = JournalPortletDataHandler.importReferencedContent(
314                            portletDataContext, entryElement, entry.getContent());
315    
316                    entry.setContent(content);
317    
318                    Calendar displayDateCal = CalendarFactoryUtil.getCalendar();
319    
320                    displayDateCal.setTime(entry.getDisplayDate());
321    
322                    int displayDateMonth = displayDateCal.get(Calendar.MONTH);
323                    int displayDateDay = displayDateCal.get(Calendar.DATE);
324                    int displayDateYear = displayDateCal.get(Calendar.YEAR);
325                    int displayDateHour = displayDateCal.get(Calendar.HOUR);
326                    int displayDateMinute = displayDateCal.get(Calendar.MINUTE);
327    
328                    if (displayDateCal.get(Calendar.AM_PM) == Calendar.PM) {
329                            displayDateHour += 12;
330                    }
331    
332                    boolean allowPingbacks = entry.isAllowPingbacks();
333                    boolean allowTrackbacks = entry.isAllowTrackbacks();
334                    String[] trackbacks = StringUtil.split(entry.getTrackbacks());
335                    int status = entry.getStatus();
336    
337                    String smallImageFileName = null;
338                    InputStream smallImageInputStream = null;
339    
340                    try {
341                            if (entry.isSmallImage()) {
342                                    String smallImagePath = entryElement.attributeValue(
343                                            "small-image-path");
344    
345                                    if (Validator.isNotNull(entry.getSmallImageURL())) {
346                                            String smallImageURL =
347                                                    JournalPortletDataHandler.importReferencedContent(
348                                                            portletDataContext, entryElement,
349                                                            entry.getSmallImageURL());
350    
351                                            entry.setSmallImageURL(smallImageURL);
352                                    }
353                                    else if (Validator.isNotNull(smallImagePath)) {
354                                            smallImageFileName = String.valueOf(
355                                                    entry.getSmallImageId()).concat(
356                                                            StringPool.PERIOD).concat(
357                                                                    entry.getSmallImageType());
358                                            smallImageInputStream =
359                                                    portletDataContext.getZipEntryAsInputStream(
360                                                            smallImagePath);
361                                    }
362                            }
363    
364                            ServiceContext serviceContext =
365                                    portletDataContext.createServiceContext(
366                                            entryElement, entry, NAMESPACE);
367    
368                            if ((status != WorkflowConstants.STATUS_APPROVED) &&
369                                    (status != WorkflowConstants.STATUS_IN_TRASH)) {
370    
371                                    serviceContext.setWorkflowAction(
372                                            WorkflowConstants.ACTION_SAVE_DRAFT);
373                            }
374    
375                            BlogsEntry importedEntry = null;
376    
377                            if (portletDataContext.isDataStrategyMirror()) {
378                                    serviceContext.setAttribute("urlTitle", entry.getUrlTitle());
379    
380                                    BlogsEntry existingEntry = BlogsEntryUtil.fetchByUUID_G(
381                                            entry.getUuid(), portletDataContext.getScopeGroupId());
382    
383                                    if (existingEntry == null) {
384                                            serviceContext.setUuid(entry.getUuid());
385    
386                                            importedEntry = BlogsEntryLocalServiceUtil.addEntry(
387                                                    userId, entry.getTitle(), entry.getDescription(),
388                                                    entry.getContent(), displayDateMonth, displayDateDay,
389                                                    displayDateYear, displayDateHour, displayDateMinute,
390                                                    allowPingbacks, allowTrackbacks, trackbacks,
391                                                    entry.isSmallImage(), entry.getSmallImageURL(),
392                                                    smallImageFileName, smallImageInputStream,
393                                                    serviceContext);
394    
395                                            if (status == WorkflowConstants.STATUS_IN_TRASH) {
396                                                    importedEntry =
397                                                            BlogsEntryLocalServiceUtil.moveEntryToTrash(
398                                                                    userId, importedEntry);
399                                            }
400                                    }
401                                    else {
402                                            importedEntry = BlogsEntryLocalServiceUtil.updateEntry(
403                                                    userId, existingEntry.getEntryId(), entry.getTitle(),
404                                                    entry.getDescription(), entry.getContent(),
405                                                    displayDateMonth, displayDateDay, displayDateYear,
406                                                    displayDateHour, displayDateMinute, allowPingbacks,
407                                                    allowTrackbacks, trackbacks, entry.getSmallImage(),
408                                                    entry.getSmallImageURL(), smallImageFileName,
409                                                    smallImageInputStream, serviceContext);
410                                    }
411                            }
412                            else {
413                                    importedEntry = BlogsEntryLocalServiceUtil.addEntry(
414                                            userId, entry.getTitle(), entry.getDescription(),
415                                            entry.getContent(), displayDateMonth, displayDateDay,
416                                            displayDateYear, displayDateHour, displayDateMinute,
417                                            allowPingbacks, allowTrackbacks, trackbacks,
418                                            entry.getSmallImage(), entry.getSmallImageURL(),
419                                            smallImageFileName, smallImageInputStream, serviceContext);
420                            }
421    
422                            portletDataContext.importClassedModel(
423                                    entry, importedEntry, NAMESPACE);
424                    }
425                    finally {
426                            StreamUtil.cleanUp(smallImageInputStream);
427                    }
428    
429            }
430    
431    }