001
014
015 package com.liferay.portlet.layoutsadmin.lar;
016
017 import com.liferay.counter.service.CounterLocalServiceUtil;
018 import com.liferay.portal.NoSuchLayoutException;
019 import com.liferay.portal.kernel.exception.PortalException;
020 import com.liferay.portal.kernel.exception.SystemException;
021 import com.liferay.portal.kernel.json.JSONFactoryUtil;
022 import com.liferay.portal.kernel.json.JSONObject;
023 import com.liferay.portal.kernel.lar.BaseStagedModelDataHandler;
024 import com.liferay.portal.kernel.lar.ExportImportPathUtil;
025 import com.liferay.portal.kernel.lar.PortletDataContext;
026 import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
027 import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
028 import com.liferay.portal.kernel.log.Log;
029 import com.liferay.portal.kernel.log.LogFactoryUtil;
030 import com.liferay.portal.kernel.staging.LayoutStagingUtil;
031 import com.liferay.portal.kernel.staging.StagingUtil;
032 import com.liferay.portal.kernel.util.ArrayUtil;
033 import com.liferay.portal.kernel.util.CharPool;
034 import com.liferay.portal.kernel.util.Constants;
035 import com.liferay.portal.kernel.util.GetterUtil;
036 import com.liferay.portal.kernel.util.LocaleUtil;
037 import com.liferay.portal.kernel.util.MapUtil;
038 import com.liferay.portal.kernel.util.ParamUtil;
039 import com.liferay.portal.kernel.util.StringBundler;
040 import com.liferay.portal.kernel.util.StringPool;
041 import com.liferay.portal.kernel.util.StringUtil;
042 import com.liferay.portal.kernel.util.UnicodeProperties;
043 import com.liferay.portal.kernel.util.Validator;
044 import com.liferay.portal.kernel.workflow.WorkflowConstants;
045 import com.liferay.portal.kernel.xml.Element;
046 import com.liferay.portal.lar.LayoutExporter;
047 import com.liferay.portal.model.Group;
048 import com.liferay.portal.model.Image;
049 import com.liferay.portal.model.Layout;
050 import com.liferay.portal.model.LayoutBranch;
051 import com.liferay.portal.model.LayoutConstants;
052 import com.liferay.portal.model.LayoutFriendlyURL;
053 import com.liferay.portal.model.LayoutPrototype;
054 import com.liferay.portal.model.LayoutRevision;
055 import com.liferay.portal.model.LayoutSet;
056 import com.liferay.portal.model.LayoutStagingHandler;
057 import com.liferay.portal.model.LayoutTemplate;
058 import com.liferay.portal.model.LayoutTypePortlet;
059 import com.liferay.portal.model.LayoutTypePortletConstants;
060 import com.liferay.portal.service.ImageLocalServiceUtil;
061 import com.liferay.portal.service.LayoutFriendlyURLLocalServiceUtil;
062 import com.liferay.portal.service.LayoutLocalServiceUtil;
063 import com.liferay.portal.service.LayoutPrototypeLocalServiceUtil;
064 import com.liferay.portal.service.LayoutRevisionLocalServiceUtil;
065 import com.liferay.portal.service.LayoutSetLocalServiceUtil;
066 import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
067 import com.liferay.portal.service.PortletLocalServiceUtil;
068 import com.liferay.portal.service.ResourceLocalServiceUtil;
069 import com.liferay.portal.service.ServiceContext;
070 import com.liferay.portal.service.ServiceContextThreadLocal;
071 import com.liferay.portal.util.PropsValues;
072 import com.liferay.portlet.journal.NoSuchArticleException;
073 import com.liferay.portlet.journal.model.JournalArticle;
074 import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
075 import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
076 import com.liferay.portlet.sites.util.SitesUtil;
077
078 import java.io.IOException;
079
080 import java.util.List;
081 import java.util.Locale;
082 import java.util.Map;
083
084
087 public class LayoutStagedModelDataHandler
088 extends BaseStagedModelDataHandler<Layout> {
089
090 public static final String[] CLASS_NAMES = {Layout.class.getName()};
091
092 @Override
093 public void deleteStagedModel(
094 String uuid, long groupId, String className, String extraData)
095 throws PortalException, SystemException {
096
097 JSONObject extraDataJSONObject = JSONFactoryUtil.createJSONObject(
098 extraData);
099
100 boolean privateLayout = extraDataJSONObject.getBoolean("privateLayout");
101
102 Layout layout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
103 uuid, groupId, privateLayout);
104
105 if (layout != null) {
106 LayoutLocalServiceUtil.deleteLayout(
107 layout, true, new ServiceContext());
108 }
109 }
110
111 @Override
112 public String[] getClassNames() {
113 return CLASS_NAMES;
114 }
115
116 @Override
117 public String getDisplayName(Layout layout) {
118 return layout.getNameCurrentValue();
119 }
120
121 protected String[] appendPortletIds(
122 String[] portletIds, String[] newPortletIds, String portletsMergeMode) {
123
124 for (String portletId : newPortletIds) {
125 if (ArrayUtil.contains(portletIds, portletId)) {
126 continue;
127 }
128
129 if (portletsMergeMode.equals(
130 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_ADD_TO_BOTTOM)) {
131
132 portletIds = ArrayUtil.append(portletIds, portletId);
133 }
134 else {
135 portletIds = ArrayUtil.append(
136 new String[] {portletId}, portletIds);
137 }
138 }
139
140 return portletIds;
141 }
142
143 @Override
144 protected void doExportStagedModel(
145 PortletDataContext portletDataContext, Layout layout)
146 throws Exception {
147
148 LayoutRevision layoutRevision = null;
149
150 ServiceContext serviceContext =
151 ServiceContextThreadLocal.getServiceContext();
152
153 boolean exportLAR = ParamUtil.getBoolean(serviceContext, "exportLAR");
154
155 if (!exportLAR && LayoutStagingUtil.isBranchingLayout(layout) &&
156 !layout.isTypeURL()) {
157
158 long layoutSetBranchId = ParamUtil.getLong(
159 serviceContext, "layoutSetBranchId");
160
161 if (layoutSetBranchId <= 0) {
162 return;
163 }
164
165 layoutRevision = LayoutRevisionLocalServiceUtil.fetchLayoutRevision(
166 layoutSetBranchId, true, layout.getPlid());
167
168 if (layoutRevision == null) {
169 return;
170 }
171
172 LayoutStagingHandler layoutStagingHandler =
173 LayoutStagingUtil.getLayoutStagingHandler(layout);
174
175 layoutStagingHandler.setLayoutRevision(layoutRevision);
176 }
177
178 Element layoutElement = portletDataContext.getExportDataElement(layout);
179
180 populateElementLayoutMetadata(layoutElement, layout, layoutRevision);
181
182 boolean deleteLayout = MapUtil.getBoolean(
183 portletDataContext.getParameterMap(), "delete_" + layout.getPlid());
184
185 if (deleteLayout) {
186 layoutElement.addAttribute("action", Constants.DELETE);
187
188 return;
189 }
190 else {
191 layoutElement.addAttribute("action", Constants.ADD);
192 }
193
194 portletDataContext.setPlid(layout.getPlid());
195
196 long parentLayoutId = layout.getParentLayoutId();
197
198 if (parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
199 Layout parentLayout = LayoutLocalServiceUtil.fetchLayout(
200 layout.getGroupId(), layout.isPrivateLayout(), parentLayoutId);
201
202 if (parentLayout != null) {
203 exportStagedModel(portletDataContext, parentLayout);
204
205 portletDataContext.addReferenceElement(
206 layout, layoutElement, parentLayout,
207 PortletDataContext.REFERENCE_TYPE_PARENT, false);
208
209 layoutElement.addAttribute(
210 "parent-layout-uuid", parentLayout.getUuid());
211 }
212 }
213
214 List<LayoutFriendlyURL> layoutFriendlyURLs =
215 LayoutFriendlyURLLocalServiceUtil.getLayoutFriendlyURLs(
216 layout.getPlid());
217
218 for (LayoutFriendlyURL layoutFriendlyURL : layoutFriendlyURLs) {
219 StagedModelDataHandlerUtil.exportStagedModel(
220 portletDataContext, layoutFriendlyURL);
221
222 portletDataContext.addReferenceElement(
223 layout, layoutElement, layoutFriendlyURL,
224 PortletDataContext.REFERENCE_TYPE_DEPENDENCY, false);
225 }
226
227 if (layout.isIconImage()) {
228 exportLayoutIconImage(portletDataContext, layout, layoutElement);
229 }
230
231 if (layout.isTypeArticle()) {
232 exportJournalArticle(portletDataContext, layout, layoutElement);
233 }
234 else if (layout.isTypeLinkToLayout()) {
235 exportLinkedLayout(portletDataContext, layout, layoutElement);
236 }
237
238 fixExportTypeSettings(layout);
239
240 portletDataContext.addClassedModel(
241 layoutElement, ExportImportPathUtil.getModelPath(layout), layout,
242 LayoutPortletDataHandler.NAMESPACE);
243 }
244
245 @Override
246 protected void doImportStagedModel(
247 PortletDataContext portletDataContext, Layout layout)
248 throws Exception {
249
250 long groupId = portletDataContext.getGroupId();
251 long userId = portletDataContext.getUserId(layout.getUserUuid());
252
253 Element layoutElement =
254 portletDataContext.getImportDataStagedModelElement(layout);
255
256 String layoutUuid = GetterUtil.getString(
257 layoutElement.attributeValue("layout-uuid"));
258
259 long layoutId = GetterUtil.getInteger(
260 layoutElement.attributeValue("layout-id"));
261
262 long oldLayoutId = layoutId;
263
264 boolean privateLayout = portletDataContext.isPrivateLayout();
265
266 Map<Long, Layout> newLayoutsMap =
267 (Map<Long, Layout>)portletDataContext.getNewPrimaryKeysMap(
268 Layout.class + ".layout");
269
270 String action = layoutElement.attributeValue("action");
271
272 if (action.equals(Constants.DELETE)) {
273 Layout deletingLayout =
274 LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
275 layoutUuid, groupId, privateLayout);
276
277 if (layout != null) {
278 newLayoutsMap.put(oldLayoutId, layout);
279
280 ServiceContext serviceContext =
281 ServiceContextThreadLocal.getServiceContext();
282
283 LayoutLocalServiceUtil.deleteLayout(
284 deletingLayout, false, serviceContext);
285 }
286
287 return;
288 }
289
290 Layout existingLayout = null;
291 Layout importedLayout = null;
292
293 String friendlyURL = layout.getFriendlyURL();
294
295 String layoutsImportMode = MapUtil.getString(
296 portletDataContext.getParameterMap(),
297 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE,
298 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_UUID);
299
300 if (layoutsImportMode.equals(
301 PortletDataHandlerKeys.LAYOUTS_IMPORT_MODE_ADD_AS_NEW)) {
302
303 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
304 groupId, privateLayout);
305 friendlyURL = StringPool.SLASH + layoutId;
306 }
307 else if (layoutsImportMode.equals(
308 PortletDataHandlerKeys.
309 LAYOUTS_IMPORT_MODE_MERGE_BY_LAYOUT_NAME)) {
310
311 Locale locale = LocaleUtil.getSiteDefault();
312
313 String localizedName = layout.getName(locale);
314
315 List<Layout> previousLayouts = LayoutLocalServiceUtil.getLayouts(
316 groupId, privateLayout);
317
318 for (Layout curLayout : previousLayouts) {
319 if (localizedName.equals(curLayout.getName(locale)) ||
320 friendlyURL.equals(curLayout.getFriendlyURL())) {
321
322 existingLayout = curLayout;
323
324 break;
325 }
326 }
327
328 if (existingLayout == null) {
329 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
330 groupId, privateLayout);
331 }
332 }
333 else if (layoutsImportMode.equals(
334 PortletDataHandlerKeys.
335 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
336
337 existingLayout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
338 layout.getUuid(), groupId, privateLayout);
339
340 if (SitesUtil.isLayoutModifiedSinceLastMerge(existingLayout)) {
341 newLayoutsMap.put(oldLayoutId, existingLayout);
342
343 return;
344 }
345
346 LayoutFriendlyURL layoutFriendlyURL =
347 LayoutFriendlyURLLocalServiceUtil.fetchFirstLayoutFriendlyURL(
348 groupId, privateLayout, friendlyURL);
349
350 if ((layoutFriendlyURL != null) && (existingLayout == null)) {
351 Layout mergeFailFriendlyURLLayout =
352 LayoutLocalServiceUtil.getLayout(
353 layoutFriendlyURL.getPlid());
354
355 SitesUtil.addMergeFailFriendlyURLLayout(
356 mergeFailFriendlyURLLayout);
357
358 return;
359 }
360 }
361 else {
362
363
364
365
366 existingLayout = LayoutLocalServiceUtil.fetchLayoutByUuidAndGroupId(
367 layout.getUuid(), groupId, privateLayout);
368
369 if (existingLayout == null) {
370 existingLayout =
371 LayoutLocalServiceUtil.fetchLayoutByFriendlyURL(
372 groupId, privateLayout, friendlyURL);
373 }
374
375 if (existingLayout == null) {
376 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
377 groupId, privateLayout);
378 }
379 }
380
381 if (_log.isDebugEnabled()) {
382 StringBundler sb = new StringBundler(7);
383
384 sb.append("Layout with {groupId=");
385 sb.append(groupId);
386 sb.append(",privateLayout=");
387 sb.append(privateLayout);
388 sb.append(",layoutId=");
389 sb.append(layoutId);
390
391 if (existingLayout == null) {
392 sb.append("} does not exist");
393
394 _log.debug(sb.toString());
395 }
396 else {
397 sb.append("} exists");
398
399 _log.debug(sb.toString());
400 }
401 }
402
403 if (existingLayout == null) {
404 long plid = CounterLocalServiceUtil.increment();
405
406 importedLayout = LayoutLocalServiceUtil.createLayout(plid);
407
408 if (layoutsImportMode.equals(
409 PortletDataHandlerKeys.
410 LAYOUTS_IMPORT_MODE_CREATED_FROM_PROTOTYPE)) {
411
412 importedLayout.setSourcePrototypeLayoutUuid(layout.getUuid());
413
414 layoutId = LayoutLocalServiceUtil.getNextLayoutId(
415 groupId, privateLayout);
416 }
417 else {
418 importedLayout.setCreateDate(layout.getCreateDate());
419 importedLayout.setModifiedDate(layout.getModifiedDate());
420 importedLayout.setLayoutPrototypeUuid(
421 layout.getLayoutPrototypeUuid());
422 importedLayout.setLayoutPrototypeLinkEnabled(
423 layout.isLayoutPrototypeLinkEnabled());
424 importedLayout.setSourcePrototypeLayoutUuid(
425 layout.getSourcePrototypeLayoutUuid());
426 }
427
428 importedLayout.setUuid(layout.getUuid());
429 importedLayout.setGroupId(groupId);
430 importedLayout.setPrivateLayout(privateLayout);
431 importedLayout.setLayoutId(layoutId);
432
433 initNewLayoutPermissions(
434 portletDataContext.getCompanyId(), groupId, userId, layout,
435 importedLayout, privateLayout);
436
437 LayoutSet layoutSet = LayoutSetLocalServiceUtil.getLayoutSet(
438 groupId, privateLayout);
439
440 importedLayout.setLayoutSet(layoutSet);
441 }
442 else {
443 importedLayout = existingLayout;
444 }
445
446 portletDataContext.setPlid(importedLayout.getPlid());
447 portletDataContext.setOldPlid(layout.getPlid());
448
449 newLayoutsMap.put(oldLayoutId, importedLayout);
450
451 long parentLayoutId = layout.getParentLayoutId();
452
453 String parentLayoutUuid = GetterUtil.getString(
454 layoutElement.attributeValue("parent-layout-uuid"));
455
456 Element parentLayoutElement =
457 portletDataContext.getReferenceDataElement(
458 layout, Layout.class, layout.getGroupId(), parentLayoutUuid);
459
460 if ((parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) &&
461 (parentLayoutElement != null)) {
462
463 String parentLayoutPath = parentLayoutElement.attributeValue(
464 "path");
465
466 Layout parentLayout =
467 (Layout)portletDataContext.getZipEntryAsObject(
468 parentLayoutPath);
469
470 StagedModelDataHandlerUtil.importStagedModel(
471 portletDataContext, parentLayout);
472
473 Layout importedParentLayout = newLayoutsMap.get(parentLayoutId);
474
475 parentLayoutId = importedParentLayout.getLayoutId();
476 }
477
478 if (_log.isDebugEnabled()) {
479 StringBundler sb = new StringBundler(4);
480
481 sb.append("Importing layout with layout id ");
482 sb.append(layoutId);
483 sb.append(" and parent layout id ");
484 sb.append(parentLayoutId);
485
486 _log.debug(sb.toString());
487 }
488
489 importedLayout.setCompanyId(portletDataContext.getCompanyId());
490 importedLayout.setParentLayoutId(parentLayoutId);
491 importedLayout.setName(layout.getName());
492 importedLayout.setTitle(layout.getTitle());
493 importedLayout.setDescription(layout.getDescription());
494 importedLayout.setKeywords(layout.getKeywords());
495 importedLayout.setRobots(layout.getRobots());
496 importedLayout.setType(layout.getType());
497
498 String portletsMergeMode = MapUtil.getString(
499 portletDataContext.getParameterMap(),
500 PortletDataHandlerKeys.PORTLETS_MERGE_MODE,
501 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE);
502
503 if (layout.isTypeArticle()) {
504 importJournalArticle(portletDataContext, layout, layoutElement);
505
506 updateTypeSettings(importedLayout, layout);
507 }
508 else if (layout.isTypePortlet() &&
509 Validator.isNotNull(layout.getTypeSettings()) &&
510 !portletsMergeMode.equals(
511 PortletDataHandlerKeys.PORTLETS_MERGE_MODE_REPLACE)) {
512
513 mergePortlets(
514 importedLayout, layout.getTypeSettings(), portletsMergeMode);
515 }
516 else if (layout.isTypeLinkToLayout()) {
517 importLinkedLayout(
518 portletDataContext, layout, importedLayout, layoutElement,
519 newLayoutsMap);
520 }
521 else {
522 updateTypeSettings(importedLayout, layout);
523 }
524
525 importedLayout.setHidden(layout.isHidden());
526 importedLayout.setFriendlyURL(
527 getUniqueFriendlyURL(
528 portletDataContext, importedLayout, friendlyURL));
529 importedLayout.setIconImage(false);
530
531 if (layout.isIconImage()) {
532 importLayoutIconImage(
533 portletDataContext, importedLayout, layoutElement);
534 }
535 else {
536 ImageLocalServiceUtil.deleteImage(importedLayout.getIconImageId());
537 }
538
539 boolean importThemeSettings = MapUtil.getBoolean(
540 portletDataContext.getParameterMap(),
541 PortletDataHandlerKeys.THEME_REFERENCE);
542
543 if (importThemeSettings) {
544 importedLayout.setThemeId(layout.getThemeId());
545 importedLayout.setColorSchemeId(layout.getColorSchemeId());
546 }
547 else {
548 importedLayout.setThemeId(StringPool.BLANK);
549 importedLayout.setColorSchemeId(StringPool.BLANK);
550 }
551
552 importedLayout.setWapThemeId(layout.getWapThemeId());
553 importedLayout.setWapColorSchemeId(layout.getWapColorSchemeId());
554 importedLayout.setCss(layout.getCss());
555 importedLayout.setPriority(layout.getPriority());
556 importedLayout.setLayoutPrototypeUuid(layout.getLayoutPrototypeUuid());
557 importedLayout.setLayoutPrototypeLinkEnabled(
558 layout.isLayoutPrototypeLinkEnabled());
559
560 StagingUtil.updateLastImportSettings(
561 layoutElement, importedLayout, portletDataContext);
562
563 fixImportTypeSettings(importedLayout);
564
565 LayoutLocalServiceUtil.updateLayout(importedLayout);
566
567 List<Layout> newLayouts = portletDataContext.getNewLayouts();
568
569 newLayouts.add(importedLayout);
570
571 Map<Long, Long> layoutPlids =
572 (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
573 Layout.class);
574
575 layoutPlids.put(layout.getPlid(), importedLayout.getPlid());
576
577 importLayoutFriendlyURLs(portletDataContext, layout);
578
579 portletDataContext.importClassedModel(
580 layout, importedLayout, LayoutPortletDataHandler.NAMESPACE);
581 }
582
583 protected void exportJournalArticle(
584 PortletDataContext portletDataContext, Layout layout,
585 Element layoutElement)
586 throws Exception {
587
588 UnicodeProperties typeSettingsProperties =
589 layout.getTypeSettingsProperties();
590
591 String articleId = typeSettingsProperties.getProperty(
592 "article-id", StringPool.BLANK);
593
594 long articleGroupId = layout.getGroupId();
595
596 if (Validator.isNull(articleId)) {
597 if (_log.isWarnEnabled()) {
598 _log.warn(
599 "No article id found in typeSettings of layout " +
600 layout.getPlid());
601 }
602 }
603
604 JournalArticle article = null;
605
606 try {
607 article = JournalArticleLocalServiceUtil.getLatestArticle(
608 articleGroupId, articleId, WorkflowConstants.STATUS_APPROVED);
609 }
610 catch (NoSuchArticleException nsae) {
611 if (_log.isWarnEnabled()) {
612 StringBundler sb = new StringBundler(4);
613
614 sb.append("No approved article found with group id ");
615 sb.append(articleGroupId);
616 sb.append(" and layout id ");
617 sb.append(articleId);
618
619 _log.warn(sb.toString());
620 }
621 }
622
623 if (article == null) {
624 return;
625 }
626
627 StagedModelDataHandlerUtil.exportStagedModel(
628 portletDataContext, article);
629
630 portletDataContext.addReferenceElement(
631 layout, layoutElement, article,
632 PortletDataContext.REFERENCE_TYPE_EMBEDDED, false);
633 }
634
635 protected void exportLayoutIconImage(
636 PortletDataContext portletDataContext, Layout layout,
637 Element layoutElement)
638 throws Exception {
639
640 Image image = ImageLocalServiceUtil.getImage(layout.getIconImageId());
641
642 if (image != null) {
643 String iconPath = ExportImportPathUtil.getModelPath(
644 portletDataContext.getScopeGroupId(), Image.class.getName(),
645 image.getImageId());
646
647 Element iconImagePathElement = layoutElement.addElement(
648 "icon-image-path");
649
650 iconImagePathElement.addText(iconPath);
651
652 portletDataContext.addZipEntry(iconPath, image.getTextObj());
653 }
654 }
655
656 protected void exportLinkedLayout(
657 PortletDataContext portletDataContext, Layout layout,
658 Element layoutElement)
659 throws Exception {
660
661 UnicodeProperties typeSettingsProperties =
662 layout.getTypeSettingsProperties();
663
664 long linkToLayoutId = GetterUtil.getLong(
665 typeSettingsProperties.getProperty(
666 "linkToLayoutId", StringPool.BLANK));
667
668 if (linkToLayoutId > 0) {
669 try {
670 Layout linkedToLayout = LayoutLocalServiceUtil.getLayout(
671 portletDataContext.getScopeGroupId(),
672 layout.isPrivateLayout(), linkToLayoutId);
673
674 exportStagedModel(portletDataContext, linkedToLayout);
675
676 portletDataContext.addReferenceElement(
677 layout, layoutElement, linkedToLayout,
678 PortletDataContext.REFERENCE_TYPE_STRONG, false);
679
680 layoutElement.addAttribute(
681 "linked-to-layout-uuid", linkedToLayout.getUuid());
682 }
683 catch (NoSuchLayoutException nsle) {
684 }
685 }
686 }
687
688 protected Object[] extractFriendlyURLInfo(Layout layout) {
689 if (!layout.isTypeURL()) {
690 return null;
691 }
692
693 UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
694
695 String url = GetterUtil.getString(typeSettings.getProperty("url"));
696
697 String friendlyURLPrivateGroupPath =
698 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_GROUP_SERVLET_MAPPING;
699 String friendlyURLPrivateUserPath =
700 PropsValues.LAYOUT_FRIENDLY_URL_PRIVATE_USER_SERVLET_MAPPING;
701 String friendlyURLPublicPath =
702 PropsValues.LAYOUT_FRIENDLY_URL_PUBLIC_SERVLET_MAPPING;
703
704 if (!url.startsWith(friendlyURLPrivateGroupPath) &&
705 !url.startsWith(friendlyURLPrivateUserPath) &&
706 !url.startsWith(friendlyURLPublicPath)) {
707
708 return null;
709 }
710
711 int x = url.indexOf(CharPool.SLASH, 1);
712
713 if (x == -1) {
714 return null;
715 }
716
717 int y = url.indexOf(CharPool.SLASH, x + 1);
718
719 if (y == -1) {
720 return null;
721 }
722
723 return new Object[] {url.substring(x, y), url, x, y};
724 }
725
726 protected void fixExportTypeSettings(Layout layout) throws Exception {
727 Object[] friendlyURLInfo = extractFriendlyURLInfo(layout);
728
729 if (friendlyURLInfo == null) {
730 return;
731 }
732
733 String friendlyURL = (String)friendlyURLInfo[0];
734
735 Group group = layout.getGroup();
736
737 String groupFriendlyURL = group.getFriendlyURL();
738
739 if (!friendlyURL.equals(groupFriendlyURL)) {
740 return;
741 }
742
743 UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
744
745 String url = (String)friendlyURLInfo[1];
746
747 int x = (Integer)friendlyURLInfo[2];
748 int y = (Integer)friendlyURLInfo[3];
749
750 typeSettings.setProperty(
751 "url",
752 url.substring(0, x) + LayoutExporter.SAME_GROUP_FRIENDLY_URL +
753 url.substring(y));
754 }
755
756 protected void fixImportTypeSettings(Layout layout) throws Exception {
757 Object[] friendlyURLInfo = extractFriendlyURLInfo(layout);
758
759 if (friendlyURLInfo == null) {
760 return;
761 }
762
763 String friendlyURL = (String)friendlyURLInfo[0];
764
765 if (!friendlyURL.equals(LayoutExporter.SAME_GROUP_FRIENDLY_URL)) {
766 return;
767 }
768
769 Group group = layout.getGroup();
770
771 UnicodeProperties typeSettings = layout.getTypeSettingsProperties();
772
773 String url = (String)friendlyURLInfo[1];
774
775 int x = (Integer)friendlyURLInfo[2];
776 int y = (Integer)friendlyURLInfo[3];
777
778 typeSettings.setProperty(
779 "url",
780 url.substring(0, x) + group.getFriendlyURL() + url.substring(y));
781 }
782
783 protected String getUniqueFriendlyURL(
784 PortletDataContext portletDataContext, Layout existingLayout,
785 String friendlyURL)
786 throws SystemException {
787
788 for (int i = 1;; i++) {
789 Layout duplicateFriendlyURLLayout =
790 LayoutLocalServiceUtil.fetchLayoutByFriendlyURL(
791 portletDataContext.getGroupId(),
792 portletDataContext.isPrivateLayout(), friendlyURL);
793
794 if ((duplicateFriendlyURLLayout == null) ||
795 (duplicateFriendlyURLLayout.getPlid() ==
796 existingLayout.getPlid())) {
797
798 break;
799 }
800
801 friendlyURL = friendlyURL + i;
802 }
803
804 return friendlyURL;
805 }
806
807 protected void importJournalArticle(
808 PortletDataContext portletDataContext, Layout layout,
809 Element layoutElement)
810 throws Exception {
811
812 UnicodeProperties typeSettingsProperties =
813 layout.getTypeSettingsProperties();
814
815 String articleId = typeSettingsProperties.getProperty(
816 "article-id", StringPool.BLANK);
817
818 if (Validator.isNull(articleId)) {
819 return;
820 }
821
822 List<Element> referenceDataElements =
823 portletDataContext.getReferenceDataElements(
824 layoutElement, JournalArticle.class);
825
826 if (!referenceDataElements.isEmpty()) {
827 StagedModelDataHandlerUtil.importStagedModel(
828 portletDataContext, referenceDataElements.get(0));
829 }
830
831 Map<String, String> articleIds =
832 (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
833 JournalArticle.class + ".articleId");
834
835 articleId = MapUtil.getString(articleIds, articleId, articleId);
836
837 typeSettingsProperties.setProperty("article-id", articleId);
838
839 JournalContentSearchLocalServiceUtil.updateContentSearch(
840 portletDataContext.getScopeGroupId(), layout.isPrivateLayout(),
841 layout.getLayoutId(), StringPool.BLANK, articleId, true);
842 }
843
844 protected void importLayoutFriendlyURLs(
845 PortletDataContext portletDataContext, Layout layout)
846 throws Exception {
847
848 List<Element> layoutFriendlyURLElements =
849 portletDataContext.getReferenceDataElements(
850 layout, LayoutFriendlyURL.class);
851
852 for (Element layoutFriendlyURLElement : layoutFriendlyURLElements) {
853 String layoutFriendlyURLPath =
854 layoutFriendlyURLElement.attributeValue("path");
855
856 LayoutFriendlyURL layoutFriendlyURL =
857 (LayoutFriendlyURL)portletDataContext.getZipEntryAsObject(
858 layoutFriendlyURLPath);
859
860 StagedModelDataHandlerUtil.importStagedModel(
861 portletDataContext, layoutFriendlyURL);
862 }
863 }
864
865 protected void importLayoutIconImage(
866 PortletDataContext portletDataContext, Layout importedLayout,
867 Element layoutElement)
868 throws Exception {
869
870 String iconImagePath = layoutElement.elementText("icon-image-path");
871
872 byte[] iconBytes = portletDataContext.getZipEntryAsByteArray(
873 iconImagePath);
874
875 if ((iconBytes != null) && (iconBytes.length > 0)) {
876 importedLayout.setIconImage(true);
877
878 if (importedLayout.getIconImageId() == 0) {
879 long iconImageId = CounterLocalServiceUtil.increment();
880
881 importedLayout.setIconImageId(iconImageId);
882 }
883
884 ImageLocalServiceUtil.updateImage(
885 importedLayout.getIconImageId(), iconBytes);
886 }
887 }
888
889 protected void importLinkedLayout(
890 PortletDataContext portletDataContext, Layout layout,
891 Layout importedLayout, Element layoutElement,
892 Map<Long, Layout> newLayoutsMap)
893 throws Exception {
894
895 UnicodeProperties typeSettingsProperties =
896 layout.getTypeSettingsProperties();
897
898 long linkToLayoutId = GetterUtil.getLong(
899 typeSettingsProperties.getProperty(
900 "linkToLayoutId", StringPool.BLANK));
901
902 String linkedToLayoutUuid = layoutElement.attributeValue(
903 "linked-to-layout-uuid");
904
905 if (linkToLayoutId <= 0) {
906 updateTypeSettings(importedLayout, layout);
907
908 return;
909 }
910
911 Element linkedToLayoutElement =
912 portletDataContext.getReferenceDataElement(
913 layout, Layout.class, layout.getGroupId(), linkedToLayoutUuid);
914
915 if (linkedToLayoutElement != null) {
916 String linkedToLayoutPath = linkedToLayoutElement.attributeValue(
917 "path");
918
919 Layout linkedToLayout =
920 (Layout)portletDataContext.getZipEntryAsObject(
921 linkedToLayoutPath);
922
923 StagedModelDataHandlerUtil.importStagedModel(
924 portletDataContext, linkedToLayout);
925
926 Layout importedLinkedLayout = newLayoutsMap.get(linkToLayoutId);
927
928 typeSettingsProperties.setProperty(
929 "privateLayout",
930 String.valueOf(importedLinkedLayout.isPrivateLayout()));
931 typeSettingsProperties.setProperty(
932 "linkToLayoutId",
933 String.valueOf(importedLinkedLayout.getLayoutId()));
934 }
935 else {
936 if (_log.isWarnEnabled()) {
937 StringBundler sb = new StringBundler(6);
938
939 sb.append("Unable to link layout with friendly URL ");
940 sb.append(layout.getFriendlyURL());
941 sb.append(" and layout id ");
942 sb.append(layout.getLayoutId());
943 sb.append(" to layout with layout id ");
944 sb.append(linkToLayoutId);
945
946 _log.warn(sb.toString());
947 }
948 }
949
950 updateTypeSettings(importedLayout, layout);
951 }
952
953 protected void initNewLayoutPermissions(
954 long companyId, long groupId, long userId, Layout layout,
955 Layout importedLayout, boolean privateLayout)
956 throws Exception {
957
958 boolean addGroupPermissions = true;
959
960 Group group = importedLayout.getGroup();
961
962 if (privateLayout && group.isUser()) {
963 addGroupPermissions = false;
964 }
965
966 boolean addGuestPermissions = false;
967
968 if (!privateLayout || layout.isTypeControlPanel()) {
969 addGuestPermissions = true;
970 }
971
972 ResourceLocalServiceUtil.addResources(
973 companyId, groupId, userId, Layout.class.getName(),
974 importedLayout.getPlid(), false, addGroupPermissions,
975 addGuestPermissions);
976 }
977
978 protected void mergePortlets(
979 Layout layout, String newTypeSettings, String portletsMergeMode) {
980
981 try {
982 UnicodeProperties previousTypeSettingsProperties =
983 layout.getTypeSettingsProperties();
984
985 LayoutTypePortlet previousLayoutType =
986 (LayoutTypePortlet)layout.getLayoutType();
987
988 LayoutTemplate previousLayoutTemplate =
989 previousLayoutType.getLayoutTemplate();
990
991 List<String> previousColumns = previousLayoutTemplate.getColumns();
992
993 UnicodeProperties newTypeSettingsProperties = new UnicodeProperties(
994 true);
995
996 newTypeSettingsProperties.load(newTypeSettings);
997
998 String layoutTemplateId = newTypeSettingsProperties.getProperty(
999 LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID);
1000
1001 previousTypeSettingsProperties.setProperty(
1002 LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID,
1003 layoutTemplateId);
1004
1005 String nestedColumnIds = newTypeSettingsProperties.getProperty(
1006 LayoutTypePortletConstants.NESTED_COLUMN_IDS);
1007
1008 if (Validator.isNotNull(nestedColumnIds)) {
1009 previousTypeSettingsProperties.setProperty(
1010 LayoutTypePortletConstants.NESTED_COLUMN_IDS,
1011 nestedColumnIds);
1012
1013 String[] nestedColumnIdsArray = StringUtil.split(
1014 nestedColumnIds);
1015
1016 for (String nestedColumnId : nestedColumnIdsArray) {
1017 String nestedColumnValue =
1018 newTypeSettingsProperties.getProperty(nestedColumnId);
1019
1020 previousTypeSettingsProperties.setProperty(
1021 nestedColumnId, nestedColumnValue);
1022 }
1023 }
1024
1025 LayoutTemplate newLayoutTemplate =
1026 LayoutTemplateLocalServiceUtil.getLayoutTemplate(
1027 layoutTemplateId, false, null);
1028
1029 String[] newPortletIds = new String[0];
1030
1031 for (String columnId : newLayoutTemplate.getColumns()) {
1032 String columnValue = newTypeSettingsProperties.getProperty(
1033 columnId);
1034
1035 String[] portletIds = StringUtil.split(columnValue);
1036
1037 if (!previousColumns.contains(columnId)) {
1038 newPortletIds = ArrayUtil.append(newPortletIds, portletIds);
1039 }
1040 else {
1041 String[] previousPortletIds = StringUtil.split(
1042 previousTypeSettingsProperties.getProperty(columnId));
1043
1044 portletIds = appendPortletIds(
1045 previousPortletIds, portletIds, portletsMergeMode);
1046
1047 previousTypeSettingsProperties.setProperty(
1048 columnId, StringUtil.merge(portletIds));
1049 }
1050 }
1051
1052
1053
1054 String columnId = previousColumns.get(0);
1055
1056 String[] portletIds = StringUtil.split(
1057 previousTypeSettingsProperties.getProperty(columnId));
1058
1059 appendPortletIds(portletIds, newPortletIds, portletsMergeMode);
1060
1061 previousTypeSettingsProperties.setProperty(
1062 columnId, StringUtil.merge(portletIds));
1063
1064 layout.setTypeSettings(previousTypeSettingsProperties.toString());
1065 }
1066 catch (IOException ioe) {
1067 layout.setTypeSettings(newTypeSettings);
1068 }
1069 }
1070
1071 protected void populateElementLayoutMetadata(
1072 Element layoutElement, Layout layout, LayoutRevision layoutRevision)
1073 throws Exception {
1074
1075 if (layoutRevision != null) {
1076 layoutElement.addAttribute(
1077 "layout-revision-id",
1078 String.valueOf(layoutRevision.getLayoutRevisionId()));
1079 layoutElement.addAttribute(
1080 "layout-branch-id",
1081 String.valueOf(layoutRevision.getLayoutBranchId()));
1082
1083 LayoutBranch layoutBranch = layoutRevision.getLayoutBranch();
1084
1085 layoutElement.addAttribute(
1086 "layout-branch-name", String.valueOf(layoutBranch.getName()));
1087 }
1088
1089 layoutElement.addAttribute("layout-uuid", layout.getUuid());
1090 layoutElement.addAttribute(
1091 "layout-id", String.valueOf(layout.getLayoutId()));
1092
1093 String layoutPrototypeUuid = layout.getLayoutPrototypeUuid();
1094
1095 if (Validator.isNotNull(layoutPrototypeUuid)) {
1096 LayoutPrototype layoutPrototype =
1097 LayoutPrototypeLocalServiceUtil.
1098 getLayoutPrototypeByUuidAndCompanyId(
1099 layoutPrototypeUuid, layout.getCompanyId());
1100
1101 layoutElement.addAttribute(
1102 "layout-prototype-uuid", layoutPrototypeUuid);
1103 layoutElement.addAttribute(
1104 "layout-prototype-name",
1105 layoutPrototype.getName(LocaleUtil.getDefault()));
1106 }
1107 }
1108
1109 protected void updateTypeSettings(Layout importedLayout, Layout layout)
1110 throws PortalException, SystemException {
1111
1112 long groupId = layout.getGroupId();
1113
1114 try {
1115 LayoutTypePortlet importedLayoutType =
1116 (LayoutTypePortlet)importedLayout.getLayoutType();
1117
1118 List<String> importedPortletIds =
1119 importedLayoutType.getPortletIds();
1120
1121 layout.setGroupId(importedLayout.getGroupId());
1122
1123 LayoutTypePortlet layoutType =
1124 (LayoutTypePortlet)layout.getLayoutType();
1125
1126 importedPortletIds.removeAll(layoutType.getPortletIds());
1127
1128 if (!importedPortletIds.isEmpty()) {
1129 PortletLocalServiceUtil.deletePortlets(
1130 importedLayout.getCompanyId(),
1131 importedPortletIds.toArray(
1132 new String[importedPortletIds.size()]),
1133 importedLayout.getPlid());
1134 }
1135
1136 importedLayout.setTypeSettings(layout.getTypeSettings());
1137
1138 }
1139 finally {
1140 layout.setGroupId(groupId);
1141 }
1142 }
1143
1144 private static Log _log = LogFactoryUtil.getLog(
1145 LayoutStagedModelDataHandler.class);
1146
1147 }