001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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
059                    };
060            }
061    
062            @Override
063            public PortletDataHandlerControl[] getExportMetadataControls() {
064                    return new PortletDataHandlerControl[] {
065                            new PortletDataHandlerBoolean(
066                                    _NAMESPACE, "blog-entries", true, _metadataControls)
067                    };
068            }
069    
070            @Override
071            public PortletDataHandlerControl[] getImportControls() {
072                    return new PortletDataHandlerControl[] {
073                            _entries, _wordpress
074                    };
075            }
076    
077            @Override
078            public PortletDataHandlerControl[] getImportMetadataControls() {
079                    return new PortletDataHandlerControl[] {
080                            new PortletDataHandlerBoolean(
081                                    _NAMESPACE, "blog-entries", true, _metadataControls)
082                    };
083            }
084    
085            @Override
086            public boolean isAlwaysExportable() {
087                    return _ALWAYS_EXPORTABLE;
088            }
089    
090            @Override
091            public boolean isPublishToLiveByDefault() {
092                    return PropsValues.BLOGS_PUBLISH_TO_LIVE_BY_DEFAULT;
093            }
094    
095            @Override
096            protected PortletPreferences doDeleteData(
097                            PortletDataContext portletDataContext, String portletId,
098                            PortletPreferences portletPreferences)
099                    throws Exception {
100    
101                    if (!portletDataContext.addPrimaryKey(
102                                    BlogsPortletDataHandlerImpl.class, "deleteData")) {
103    
104                            BlogsEntryLocalServiceUtil.deleteEntries(
105                                    portletDataContext.getScopeGroupId());
106                    }
107    
108                    return null;
109            }
110    
111            @Override
112            protected String doExportData(
113                            PortletDataContext portletDataContext, String portletId,
114                            PortletPreferences portletPreferences)
115                    throws Exception {
116    
117                    portletDataContext.addPermissions(
118                            "com.liferay.portlet.blogs", portletDataContext.getScopeGroupId());
119    
120                    Document document = SAXReaderUtil.createDocument();
121    
122                    Element rootElement = document.addElement("blogs-data");
123    
124                    rootElement.addAttribute(
125                            "group-id", String.valueOf(portletDataContext.getScopeGroupId()));
126    
127                    Element entriesElement = rootElement.addElement("entries");
128    
129                    Element dlFileEntryTypesElement = entriesElement.addElement(
130                            "dl-file-entry-types");
131                    Element dlFoldersElement = entriesElement.addElement("dl-folders");
132                    Element dlFileEntriesElement = entriesElement.addElement(
133                            "dl-file-entries");
134                    Element dlFileRanksElement = entriesElement.addElement("dl-file-ranks");
135                    Element dlRepositoriesElement = entriesElement.addElement(
136                            "dl-repositories");
137                    Element dlRepositoryEntriesElement = entriesElement.addElement(
138                            "dl-repository-entries");
139    
140                    List<BlogsEntry> entries = BlogsEntryUtil.findByGroupId(
141                            portletDataContext.getScopeGroupId());
142    
143                    for (BlogsEntry entry : entries) {
144                            exportEntry(
145                                    portletDataContext, entriesElement, dlFileEntryTypesElement,
146                                    dlFoldersElement, dlFileEntriesElement, dlFileRanksElement,
147                                    dlRepositoriesElement, dlRepositoryEntriesElement, entry);
148                    }
149    
150                    return document.formattedString();
151            }
152    
153            @Override
154            protected PortletPreferences doImportData(
155                            PortletDataContext portletDataContext, String portletId,
156                            PortletPreferences portletPreferences, String data)
157                    throws Exception {
158    
159                    portletDataContext.importPermissions(
160                            "com.liferay.portlet.blogs", portletDataContext.getSourceGroupId(),
161                            portletDataContext.getScopeGroupId());
162    
163                    Document document = SAXReaderUtil.read(data);
164    
165                    Element rootElement = document.getRootElement();
166    
167                    Element entriesElement = rootElement.element("entries");
168    
169                    if (entriesElement != null) {
170                            JournalPortletDataHandlerImpl.importReferencedData(
171                                    portletDataContext, entriesElement);
172                    }
173                    else {
174                            entriesElement = rootElement;
175                    }
176    
177                    for (Element entryElement : entriesElement.elements("entry")) {
178                            String path = entryElement.attributeValue("path");
179    
180                            if (!portletDataContext.isPathNotProcessed(path)) {
181                                    continue;
182                            }
183    
184                            BlogsEntry entry =
185                                    (BlogsEntry)portletDataContext.getZipEntryAsObject(path);
186    
187                            importEntry(portletDataContext, entryElement, entry);
188                    }
189    
190                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "wordpress")) {
191                            WordPressImporter.importData(portletDataContext);
192                    }
193    
194                    return null;
195            }
196    
197            protected void exportEntry(
198                            PortletDataContext portletDataContext, Element entriesElement,
199                            Element dlFileEntryTypesElement, Element dlFoldersElement,
200                            Element dlFileEntriesElement, Element dlFileRanksElement,
201                            Element dlRepositoriesElement, Element dlRepositoryEntriesElement,
202                            BlogsEntry entry)
203                    throws Exception {
204    
205                    if (!portletDataContext.isWithinDateRange(entry.getModifiedDate())) {
206                            return;
207                    }
208    
209                    if (entry.getStatus() != WorkflowConstants.STATUS_APPROVED) {
210                            return;
211                    }
212    
213                    String path = getEntryPath(portletDataContext, entry);
214    
215                    if (!portletDataContext.isPathNotProcessed(path)) {
216                            return;
217                    }
218    
219                    // Clone this entry to make sure changes to its content are never
220                    // persisted
221    
222                    entry = (BlogsEntry)entry.clone();
223    
224                    Element entryElement = (Element)entriesElement.selectSingleNode(
225                            "//page[@path='".concat(path).concat("']"));
226    
227                    if (entryElement == null) {
228                            entryElement = entriesElement.addElement("entry");
229                    }
230    
231                    String content = JournalPortletDataHandlerImpl.exportReferencedContent(
232                            portletDataContext, dlFileEntryTypesElement, dlFoldersElement,
233                            dlFileEntriesElement, dlFileRanksElement, dlRepositoriesElement,
234                            dlRepositoryEntriesElement, entryElement, entry.getContent());
235    
236                    entry.setContent(content);
237    
238                    String imagePath = getEntryImagePath(portletDataContext, entry);
239    
240                    entryElement.addAttribute("image-path", imagePath);
241    
242                    Image smallImage = ImageUtil.fetchByPrimaryKey(entry.getSmallImageId());
243    
244                    if (entry.isSmallImage() && (smallImage != null)) {
245                            String smallImagePath = getEntrySmallImagePath(
246                                    portletDataContext, entry);
247    
248                            entryElement.addAttribute("small-image-path", smallImagePath);
249    
250                            entry.setSmallImageType(smallImage.getType());
251    
252                            portletDataContext.addZipEntry(
253                                    smallImagePath, smallImage.getTextObj());
254                    }
255    
256                    portletDataContext.addClassedModel(
257                            entryElement, path, entry, _NAMESPACE);
258            }
259    
260            protected String getEntryImagePath(
261                            PortletDataContext portletDataContext, BlogsEntry entry)
262                    throws Exception {
263    
264                    StringBundler sb = new StringBundler(4);
265    
266                    sb.append(portletDataContext.getPortletPath(PortletKeys.BLOGS));
267                    sb.append("/entry/");
268                    sb.append(entry.getUuid());
269                    sb.append(StringPool.SLASH);
270    
271                    return sb.toString();
272            }
273    
274            protected String getEntryPath(
275                    PortletDataContext portletDataContext, BlogsEntry entry) {
276    
277                    StringBundler sb = new StringBundler(4);
278    
279                    sb.append(portletDataContext.getPortletPath(PortletKeys.BLOGS));
280                    sb.append("/entries/");
281                    sb.append(entry.getEntryId());
282                    sb.append(".xml");
283    
284                    return sb.toString();
285            }
286    
287            protected String getEntrySmallImagePath(
288                            PortletDataContext portletDataContext, BlogsEntry entry)
289                    throws Exception {
290    
291                    StringBundler sb = new StringBundler(6);
292    
293                    sb.append(portletDataContext.getPortletPath(PortletKeys.BLOGS));
294                    sb.append("/entries/");
295                    sb.append(entry.getUuid());
296                    sb.append("/thumbnail");
297                    sb.append(StringPool.PERIOD);
298                    sb.append(entry.getSmallImageType());
299    
300                    return sb.toString();
301            }
302    
303            protected void importEntry(
304                            PortletDataContext portletDataContext, Element entryElement,
305                            BlogsEntry entry)
306                    throws Exception {
307    
308                    long userId = portletDataContext.getUserId(entry.getUserUuid());
309    
310                    String content = JournalPortletDataHandlerImpl.importReferencedContent(
311                            portletDataContext, entryElement, entry.getContent());
312    
313                    entry.setContent(content);
314    
315                    Calendar displayDateCal = CalendarFactoryUtil.getCalendar();
316    
317                    displayDateCal.setTime(entry.getDisplayDate());
318    
319                    int displayDateMonth = displayDateCal.get(Calendar.MONTH);
320                    int displayDateDay = displayDateCal.get(Calendar.DATE);
321                    int displayDateYear = displayDateCal.get(Calendar.YEAR);
322                    int displayDateHour = displayDateCal.get(Calendar.HOUR);
323                    int displayDateMinute = displayDateCal.get(Calendar.MINUTE);
324    
325                    if (displayDateCal.get(Calendar.AM_PM) == Calendar.PM) {
326                            displayDateHour += 12;
327                    }
328    
329                    boolean allowPingbacks = entry.isAllowPingbacks();
330                    boolean allowTrackbacks = entry.isAllowTrackbacks();
331                    String[] trackbacks = StringUtil.split(entry.getTrackbacks());
332                    int status = entry.getStatus();
333    
334                    ServiceContext serviceContext = portletDataContext.createServiceContext(
335                            entryElement, entry, _NAMESPACE);
336    
337                    if (status != WorkflowConstants.STATUS_APPROVED) {
338                            serviceContext.setWorkflowAction(
339                                    WorkflowConstants.ACTION_SAVE_DRAFT);
340                    }
341    
342                    String smallImageFileName = null;
343                    InputStream smallImageInputStream = null;
344    
345                    try {
346                            String smallImagePath = entryElement.attributeValue(
347                                    "small-image-path");
348    
349                            if (entry.isSmallImage() && Validator.isNotNull(smallImagePath)) {
350                                    smallImageFileName = String.valueOf(
351                                            entry.getSmallImageId()).concat(
352                                                    StringPool.PERIOD).concat(entry.getSmallImageType());
353                                    smallImageInputStream =
354                                            portletDataContext.getZipEntryAsInputStream(smallImagePath);
355                            }
356    
357                            BlogsEntry importedEntry = null;
358    
359                            if (portletDataContext.isDataStrategyMirror()) {
360                                    BlogsEntry existingEntry = BlogsEntryUtil.fetchByUUID_G(
361                                            entry.getUuid(), portletDataContext.getScopeGroupId());
362    
363                                    if (existingEntry == null) {
364                                            serviceContext.setUuid(entry.getUuid());
365    
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.isSmallImage(), entry.getSmallImageURL(),
372                                                    smallImageFileName, smallImageInputStream,
373                                                    serviceContext);
374                                    }
375                                    else {
376                                            importedEntry = BlogsEntryLocalServiceUtil.updateEntry(
377                                                    userId, existingEntry.getEntryId(), entry.getTitle(),
378                                                    entry.getDescription(), entry.getContent(),
379                                                    displayDateMonth, displayDateDay, displayDateYear,
380                                                    displayDateHour, displayDateMinute, allowPingbacks,
381                                                    allowTrackbacks, trackbacks, entry.getSmallImage(),
382                                                    entry.getSmallImageURL(), smallImageFileName,
383                                                    smallImageInputStream, serviceContext);
384                                    }
385                            }
386                            else {
387                                    importedEntry = BlogsEntryLocalServiceUtil.addEntry(
388                                            userId, entry.getTitle(), entry.getDescription(),
389                                            entry.getContent(), displayDateMonth, displayDateDay,
390                                            displayDateYear, displayDateHour, displayDateMinute,
391                                            allowPingbacks, allowTrackbacks, trackbacks,
392                                            entry.getSmallImage(), entry.getSmallImageURL(),
393                                            smallImageFileName, smallImageInputStream, serviceContext);
394                            }
395    
396                            portletDataContext.importClassedModel(
397                                    entry, importedEntry, _NAMESPACE);
398                    }
399                    finally {
400                            StreamUtil.cleanUp(smallImageInputStream);
401                    }
402    
403            }
404    
405            private static final boolean _ALWAYS_EXPORTABLE = true;
406    
407            private static final String _NAMESPACE = "blogs";
408    
409            private static PortletDataHandlerBoolean _entries =
410                    new PortletDataHandlerBoolean(_NAMESPACE, "entries", true, true);
411    
412            private static PortletDataHandlerControl[] _metadataControls =
413                    new PortletDataHandlerControl[] {
414                            new PortletDataHandlerBoolean(_NAMESPACE, "categories"),
415                            new PortletDataHandlerBoolean(_NAMESPACE, "comments"),
416                            new PortletDataHandlerBoolean(_NAMESPACE, "ratings"),
417                            new PortletDataHandlerBoolean(_NAMESPACE, "tags")
418                    };
419    
420            private static PortletDataHandlerBoolean _wordpress =
421                    new PortletDataHandlerBoolean(_NAMESPACE, "wordpress");
422    
423    }