001    /**
002     * Copyright (c) 2000-2011 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                    Element igFoldersElement = entriesElement.addElement("ig-folders");
120                    Element igImagesElement = entriesElement.addElement("ig-images");
121    
122                    List<BlogsEntry> entries = BlogsEntryUtil.findByGroupId(
123                            portletDataContext.getScopeGroupId());
124    
125                    for (BlogsEntry entry : entries) {
126                            exportEntry(
127                                    portletDataContext, entriesElement, dlFileEntryTypesElement,
128                                    dlFoldersElement, dlFileEntriesElement, dlFileRanksElement,
129                                    igFoldersElement, igImagesElement, entry, false);
130                    }
131    
132                    return document.formattedString();
133            }
134    
135            @Override
136            protected PortletPreferences doImportData(
137                            PortletDataContext portletDataContext, String portletId,
138                            PortletPreferences portletPreferences, String data)
139                    throws Exception {
140    
141                    portletDataContext.importPermissions(
142                            "com.liferay.portlet.blogs", portletDataContext.getSourceGroupId(),
143                            portletDataContext.getScopeGroupId());
144    
145                    Document document = SAXReaderUtil.read(data);
146    
147                    Element rootElement = document.getRootElement();
148    
149                    Element entriesElement = rootElement.element("entries");
150    
151                    if (entriesElement != null) {
152                            JournalPortletDataHandlerImpl.importReferencedData(
153                                    portletDataContext, entriesElement);
154                    }
155                    else {
156                            entriesElement = rootElement;
157                    }
158    
159                    for (Element entryElement : entriesElement.elements("entry")) {
160                            String path = entryElement.attributeValue("path");
161    
162                            if (!portletDataContext.isPathNotProcessed(path)) {
163                                    continue;
164                            }
165    
166                            BlogsEntry entry =
167                                    (BlogsEntry)portletDataContext.getZipEntryAsObject(path);
168    
169                            importEntry(portletDataContext, entryElement, entry);
170                    }
171    
172                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "wordpress")) {
173                            WordPressImporter.importData(portletDataContext);
174                    }
175    
176                    return null;
177            }
178    
179            protected void exportEntry(
180                            PortletDataContext portletDataContext, Element entriesElement,
181                            Element dlFileEntryTypesElement, Element dlFoldersElement,
182                            Element dlFileEntriesElement, Element dlFileRanksElement,
183                            Element igFoldersElement, Element igImagesElement, BlogsEntry entry,
184                            boolean checkDateRange)
185                    throws Exception {
186    
187                    if (!portletDataContext.isWithinDateRange(entry.getModifiedDate())) {
188                            return;
189                    }
190    
191                    if (entry.getStatus() != WorkflowConstants.STATUS_APPROVED) {
192                            return;
193                    }
194    
195                    String path = getEntryPath(portletDataContext, entry);
196    
197                    if (!portletDataContext.isPathNotProcessed(path)) {
198                            return;
199                    }
200    
201                    // Clone this entry to make sure changes to its content are never
202                    // persisted
203    
204                    entry = (BlogsEntry)entry.clone();
205    
206                    Element entryElement = (Element)entriesElement.selectSingleNode(
207                            "//page[@path='".concat(path).concat("']"));
208    
209                    if (entryElement == null) {
210                            entryElement = entriesElement.addElement("entry");
211                    }
212    
213                    String content = JournalPortletDataHandlerImpl.exportReferencedContent(
214                            portletDataContext, dlFileEntryTypesElement, dlFoldersElement,
215                            dlFileEntriesElement, dlFileRanksElement, igFoldersElement,
216                            igImagesElement, entryElement, entry.getContent(), checkDateRange);
217    
218                    entry.setContent(content);
219    
220                    String imagePath = getEntryImagePath(portletDataContext, entry);
221    
222                    entryElement.addAttribute("image-path", imagePath);
223    
224                    Image smallImage = ImageUtil.fetchByPrimaryKey(entry.getSmallImageId());
225    
226                    if (entry.isSmallImage() && (smallImage != null)) {
227                            String smallImagePath = getEntrySmallImagePath(
228                                    portletDataContext, entry);
229    
230                            entryElement.addAttribute("small-image-path", smallImagePath);
231    
232                            entry.setSmallImageType(smallImage.getType());
233    
234                            portletDataContext.addZipEntry(
235                                    smallImagePath, smallImage.getTextObj());
236                    }
237    
238                    portletDataContext.addClassedModel(
239                            entryElement, path, entry, _NAMESPACE);
240            }
241    
242            protected String getEntryImagePath(
243                            PortletDataContext portletDataContext, BlogsEntry entry)
244                    throws Exception {
245    
246                    StringBundler sb = new StringBundler(4);
247    
248                    sb.append(portletDataContext.getPortletPath(PortletKeys.BLOGS));
249                    sb.append("/entry/");
250                    sb.append(entry.getUuid());
251                    sb.append(StringPool.SLASH);
252    
253                    return sb.toString();
254            }
255    
256            protected String getEntryPath(
257                    PortletDataContext portletDataContext, BlogsEntry entry) {
258    
259                    StringBundler sb = new StringBundler(4);
260    
261                    sb.append(portletDataContext.getPortletPath(PortletKeys.BLOGS));
262                    sb.append("/entries/");
263                    sb.append(entry.getEntryId());
264                    sb.append(".xml");
265    
266                    return sb.toString();
267            }
268    
269            protected String getEntrySmallImagePath(
270                            PortletDataContext portletDataContext, BlogsEntry entry)
271                    throws Exception {
272    
273                    StringBundler sb = new StringBundler(6);
274    
275                    sb.append(portletDataContext.getPortletPath(PortletKeys.BLOGS));
276                    sb.append("/entries/");
277                    sb.append(entry.getUuid());
278                    sb.append("/thumbnail");
279                    sb.append(StringPool.PERIOD);
280                    sb.append(entry.getSmallImageType());
281    
282                    return sb.toString();
283            }
284    
285            protected void importEntry(
286                            PortletDataContext portletDataContext, Element entryElement,
287                            BlogsEntry entry)
288                    throws Exception {
289    
290                    long userId = portletDataContext.getUserId(entry.getUserUuid());
291    
292                    String content = JournalPortletDataHandlerImpl.importReferencedContent(
293                            portletDataContext, entryElement, entry.getContent());
294    
295                    entry.setContent(content);
296    
297                    Calendar displayDateCal = CalendarFactoryUtil.getCalendar();
298    
299                    displayDateCal.setTime(entry.getDisplayDate());
300    
301                    int displayDateMonth = displayDateCal.get(Calendar.MONTH);
302                    int displayDateDay = displayDateCal.get(Calendar.DATE);
303                    int displayDateYear = displayDateCal.get(Calendar.YEAR);
304                    int displayDateHour = displayDateCal.get(Calendar.HOUR);
305                    int displayDateMinute = displayDateCal.get(Calendar.MINUTE);
306    
307                    if (displayDateCal.get(Calendar.AM_PM) == Calendar.PM) {
308                            displayDateHour += 12;
309                    }
310    
311                    boolean allowPingbacks = entry.isAllowPingbacks();
312                    boolean allowTrackbacks = entry.isAllowTrackbacks();
313                    String[] trackbacks = StringUtil.split(entry.getTrackbacks());
314                    int status = entry.getStatus();
315    
316                    ServiceContext serviceContext = portletDataContext.createServiceContext(
317                            entryElement, entry, _NAMESPACE);
318    
319                    if (status != WorkflowConstants.STATUS_APPROVED) {
320                            serviceContext.setWorkflowAction(
321                                    WorkflowConstants.ACTION_SAVE_DRAFT);
322                    }
323    
324                    String smallImageFileName = null;
325                    InputStream smallImageInputStream = null;
326    
327                    try {
328                            String smallImagePath = entryElement.attributeValue(
329                                    "small-image-path");
330    
331                            if (entry.isSmallImage() && Validator.isNotNull(smallImagePath)) {
332                                    smallImageFileName =
333                                            String.valueOf(entry.getSmallImageId()).concat(
334                                                    StringPool.PERIOD).concat(entry.getSmallImageType());
335                                    smallImageInputStream =
336                                            portletDataContext.getZipEntryAsInputStream(smallImagePath);
337                            }
338    
339                            BlogsEntry importedEntry = null;
340    
341                            if (portletDataContext.isDataStrategyMirror()) {
342                                    BlogsEntry existingEntry = BlogsEntryUtil.fetchByUUID_G(
343                                            entry.getUuid(), portletDataContext.getScopeGroupId());
344    
345                                    if (existingEntry == null) {
346                                            serviceContext.setUuid(entry.getUuid());
347    
348                                            importedEntry = BlogsEntryLocalServiceUtil.addEntry(
349                                                    userId, entry.getTitle(), entry.getDescription(),
350                                                    entry.getContent(), displayDateMonth, displayDateDay,
351                                                    displayDateYear, displayDateHour, displayDateMinute,
352                                                    allowPingbacks, allowTrackbacks, trackbacks,
353                                                    entry.isSmallImage(), entry.getSmallImageURL(),
354                                                    smallImageFileName, smallImageInputStream,
355                                                    serviceContext);
356                                    }
357                                    else {
358                                            importedEntry = BlogsEntryLocalServiceUtil.updateEntry(
359                                                    userId, existingEntry.getEntryId(), entry.getTitle(),
360                                                    entry.getDescription(), entry.getContent(),
361                                                    displayDateMonth, displayDateDay, displayDateYear,
362                                                    displayDateHour, displayDateMinute, allowPingbacks,
363                                                    allowTrackbacks, trackbacks, entry.getSmallImage(),
364                                                    entry.getSmallImageURL(), smallImageFileName,
365                                                    smallImageInputStream, serviceContext);
366                                    }
367                            }
368                            else {
369                                    importedEntry = BlogsEntryLocalServiceUtil.addEntry(
370                                            userId, entry.getTitle(), entry.getDescription(),
371                                            entry.getContent(), displayDateMonth, displayDateDay,
372                                            displayDateYear, displayDateHour, displayDateMinute,
373                                            allowPingbacks, allowTrackbacks, trackbacks,
374                                            entry.getSmallImage(), entry.getSmallImageURL(),
375                                            smallImageFileName, smallImageInputStream,
376                                            serviceContext);
377                            }
378    
379                            portletDataContext.importClassedModel(
380                                    entry, importedEntry, _NAMESPACE);
381                    }
382                    finally {
383                            StreamUtil.cleanUp(smallImageInputStream);
384                    }
385    
386            }
387    
388            private static final boolean _ALWAYS_EXPORTABLE = true;
389    
390            private static final String _NAMESPACE = "blogs";
391    
392            private static PortletDataHandlerBoolean _categories =
393                    new PortletDataHandlerBoolean(_NAMESPACE, "categories");
394    
395            private static PortletDataHandlerBoolean _comments =
396                    new PortletDataHandlerBoolean(_NAMESPACE, "comments");
397    
398            private static PortletDataHandlerBoolean _entries =
399                    new PortletDataHandlerBoolean(_NAMESPACE, "entries", true, true);
400    
401            private static PortletDataHandlerBoolean _ratings =
402                    new PortletDataHandlerBoolean(_NAMESPACE, "ratings");
403    
404            private static PortletDataHandlerBoolean _tags =
405                    new PortletDataHandlerBoolean(_NAMESPACE, "tags");
406    
407            private static PortletDataHandlerBoolean _wordpress =
408                    new PortletDataHandlerBoolean(_NAMESPACE, "wordpress");
409    
410    }