001
014
015 package com.liferay.portlet.layoutsadmin.util;
016
017 import com.liferay.exportimport.kernel.staging.LayoutStagingUtil;
018 import com.liferay.exportimport.kernel.staging.StagingUtil;
019 import com.liferay.portal.kernel.dao.orm.QueryUtil;
020 import com.liferay.portal.kernel.exception.PortalException;
021 import com.liferay.portal.kernel.json.JSONArray;
022 import com.liferay.portal.kernel.json.JSONFactoryUtil;
023 import com.liferay.portal.kernel.json.JSONObject;
024 import com.liferay.portal.kernel.log.Log;
025 import com.liferay.portal.kernel.log.LogFactoryUtil;
026 import com.liferay.portal.kernel.model.Group;
027 import com.liferay.portal.kernel.model.Layout;
028 import com.liferay.portal.kernel.model.LayoutBranch;
029 import com.liferay.portal.kernel.model.LayoutConstants;
030 import com.liferay.portal.kernel.model.LayoutRevision;
031 import com.liferay.portal.kernel.model.LayoutSetBranch;
032 import com.liferay.portal.kernel.model.impl.VirtualLayout;
033 import com.liferay.portal.kernel.security.permission.ActionKeys;
034 import com.liferay.portal.kernel.service.LayoutLocalServiceUtil;
035 import com.liferay.portal.kernel.service.LayoutServiceUtil;
036 import com.liferay.portal.kernel.service.LayoutSetBranchLocalServiceUtil;
037 import com.liferay.portal.kernel.service.permission.GroupPermissionUtil;
038 import com.liferay.portal.kernel.service.permission.LayoutPermissionUtil;
039 import com.liferay.portal.kernel.theme.ThemeDisplay;
040 import com.liferay.portal.kernel.util.ArrayUtil;
041 import com.liferay.portal.kernel.util.ParamUtil;
042 import com.liferay.portal.kernel.util.SessionClicks;
043 import com.liferay.portal.kernel.util.StringBundler;
044 import com.liferay.portal.kernel.util.StringPool;
045 import com.liferay.portal.kernel.util.WebKeys;
046 import com.liferay.portal.util.PropsValues;
047 import com.liferay.sites.kernel.util.SitesUtil;
048
049 import java.util.ArrayList;
050 import java.util.Collections;
051 import java.util.Iterator;
052 import java.util.List;
053
054 import javax.servlet.http.HttpServletRequest;
055 import javax.servlet.http.HttpSession;
056
057
065 public class LayoutsTreeUtil {
066
067 public static String getLayoutsJSON(
068 HttpServletRequest request, long groupId, boolean privateLayout,
069 long parentLayoutId, boolean incomplete, String treeId)
070 throws Exception {
071
072 return getLayoutsJSON(
073 request, groupId, privateLayout, parentLayoutId, null, incomplete,
074 treeId);
075 }
076
077 public static String getLayoutsJSON(
078 HttpServletRequest request, long groupId, boolean privateLayout,
079 long parentLayoutId, long[] expandedLayoutIds, boolean incomplete,
080 String treeId)
081 throws Exception {
082
083 if (_log.isDebugEnabled()) {
084 StringBundler sb = new StringBundler(13);
085
086 sb.append("getLayoutsJSON(groupId=");
087 sb.append(groupId);
088 sb.append(", privateLayout=");
089 sb.append(privateLayout);
090 sb.append(", parentLayoutId=");
091 sb.append(parentLayoutId);
092 sb.append(", expandedLayoutIds=");
093 sb.append(expandedLayoutIds);
094 sb.append(", incomplete=");
095 sb.append(incomplete);
096 sb.append(", treeId=");
097 sb.append(treeId);
098 sb.append(StringPool.CLOSE_PARENTHESIS);
099
100 _log.debug(sb.toString());
101 }
102
103 LayoutTreeNodes layoutTreeNodes = _getLayoutTreeNodes(
104 request, groupId, privateLayout, parentLayoutId, incomplete,
105 expandedLayoutIds, treeId);
106
107 return _toJSON(request, groupId, layoutTreeNodes);
108 }
109
110 public static String getLayoutsJSON(
111 HttpServletRequest request, long groupId, String treeId)
112 throws Exception {
113
114 if (_log.isDebugEnabled()) {
115 StringBundler sb = new StringBundler(5);
116
117 sb.append("getLayoutsJSON(groupId=");
118 sb.append(groupId);
119 sb.append(", treeId=");
120 sb.append(treeId);
121 sb.append(StringPool.CLOSE_PARENTHESIS);
122
123 _log.debug(sb.toString());
124 }
125
126 LayoutTreeNodes layoutTreeNodes = new LayoutTreeNodes();
127
128 layoutTreeNodes.addAll(
129 _getLayoutTreeNodes(
130 request, groupId, true,
131 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID, false, null, treeId));
132 layoutTreeNodes.addAll(
133 _getLayoutTreeNodes(
134 request, groupId, false,
135 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID, false, null, treeId));
136
137 return _toJSON(request, groupId, layoutTreeNodes);
138 }
139
140 private static Layout _fetchCurrentLayout(HttpServletRequest request) {
141 long selPlid = ParamUtil.getLong(request, "selPlid");
142
143 if (selPlid > 0) {
144 return LayoutLocalServiceUtil.fetchLayout(selPlid);
145 }
146
147 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
148 WebKeys.THEME_DISPLAY);
149
150 Layout layout = themeDisplay.getLayout();
151
152 if (!layout.isTypeControlPanel()) {
153 return layout;
154 }
155
156 return null;
157 }
158
159 private static List<Layout> _getAncestorLayouts(HttpServletRequest request)
160 throws Exception {
161
162 Layout layout = _fetchCurrentLayout(request);
163
164 if (layout == null) {
165 return Collections.emptyList();
166 }
167
168 List<Layout> ancestorLayouts = LayoutServiceUtil.getAncestorLayouts(
169 layout.getPlid());
170
171 if (_log.isDebugEnabled()) {
172 StringBundler sb = new StringBundler(7);
173
174 sb.append("_getAncestorLayouts(plid=");
175 sb.append(layout.getPlid());
176 sb.append(", ancestorLayouts=");
177 sb.append(ancestorLayouts);
178 sb.append(", layout=");
179 sb.append(layout);
180 sb.append(StringPool.CLOSE_PARENTHESIS);
181
182 _log.debug(sb.toString());
183 }
184
185 ancestorLayouts.add(layout);
186
187 return ancestorLayouts;
188 }
189
190 private static LayoutTreeNodes _getLayoutTreeNodes(
191 HttpServletRequest request, long groupId, boolean privateLayout,
192 long parentLayoutId, boolean incomplete, long[] expandedLayoutIds,
193 String treeId)
194 throws Exception {
195
196 if (_log.isDebugEnabled()) {
197 StringBundler sb = new StringBundler(13);
198
199 sb.append("_getLayoutTreeNodes(groupId=");
200 sb.append(groupId);
201 sb.append(", privateLayout=");
202 sb.append(privateLayout);
203 sb.append(", parentLayoutId=");
204 sb.append(parentLayoutId);
205 sb.append(", expandedLayoutIds=");
206 sb.append(expandedLayoutIds);
207 sb.append(", incomplete=");
208 sb.append(incomplete);
209 sb.append(", treeId=");
210 sb.append(treeId);
211 sb.append(StringPool.CLOSE_PARENTHESIS);
212
213 _log.debug(sb.toString());
214 }
215
216 List<LayoutTreeNode> layoutTreeNodes = new ArrayList<>();
217
218 List<Layout> ancestorLayouts = _getAncestorLayouts(request);
219
220 List<Layout> layouts = LayoutServiceUtil.getLayouts(
221 groupId, privateLayout, parentLayoutId, incomplete,
222 QueryUtil.ALL_POS, QueryUtil.ALL_POS);
223
224 for (Layout layout :
225 _paginateLayouts(
226 request, groupId, privateLayout, parentLayoutId, layouts,
227 treeId)) {
228
229 LayoutTreeNode layoutTreeNode = new LayoutTreeNode(layout);
230
231 LayoutTreeNodes childLayoutTreeNodes = null;
232
233 if (_isExpandableLayout(
234 request, ancestorLayouts, expandedLayoutIds, layout)) {
235
236 if (layout instanceof VirtualLayout) {
237 VirtualLayout virtualLayout = (VirtualLayout)layout;
238
239 childLayoutTreeNodes = _getLayoutTreeNodes(
240 request, virtualLayout.getSourceGroupId(),
241 virtualLayout.isPrivateLayout(),
242 virtualLayout.getLayoutId(), incomplete,
243 expandedLayoutIds, treeId);
244 }
245 else {
246 childLayoutTreeNodes = _getLayoutTreeNodes(
247 request, groupId, layout.isPrivateLayout(),
248 layout.getLayoutId(), incomplete, expandedLayoutIds,
249 treeId);
250 }
251 }
252 else {
253 int childLayoutsCount = LayoutServiceUtil.getLayoutsCount(
254 groupId, privateLayout, layout.getLayoutId());
255
256 childLayoutTreeNodes = new LayoutTreeNodes(
257 new ArrayList<LayoutTreeNode>(), childLayoutsCount);
258 }
259
260 layoutTreeNode.setChildLayoutTreeNodes(childLayoutTreeNodes);
261
262 layoutTreeNodes.add(layoutTreeNode);
263 }
264
265 return new LayoutTreeNodes(layoutTreeNodes, layouts.size());
266 }
267
268 private static int _getLoadedLayoutsCount(
269 HttpSession session, long groupId, boolean privateLayout,
270 long layoutId, String treeId)
271 throws Exception {
272
273 StringBundler sb = new StringBundler(7);
274
275 sb.append(treeId);
276 sb.append(StringPool.COLON);
277 sb.append(groupId);
278 sb.append(StringPool.COLON);
279 sb.append(privateLayout);
280 sb.append(StringPool.COLON);
281 sb.append("Pagination");
282
283 String key = sb.toString();
284
285 String paginationJSON = SessionClicks.get(
286 session, key, JSONFactoryUtil.getNullJSON());
287
288 JSONObject paginationJSONObject = JSONFactoryUtil.createJSONObject(
289 paginationJSON);
290
291 if (_log.isDebugEnabled()) {
292 sb = new StringBundler(9);
293
294 sb.append("_getLoadedLayoutsCount(key=");
295 sb.append(key);
296 sb.append(", layoutId=");
297 sb.append(layoutId);
298 sb.append(", paginationJSON=");
299 sb.append(paginationJSON);
300 sb.append(", paginationJSONObject");
301 sb.append(paginationJSONObject);
302 sb.append(StringPool.CLOSE_PARENTHESIS);
303
304 _log.debug(sb.toString());
305 }
306
307 return paginationJSONObject.getInt(String.valueOf(layoutId), 0);
308 }
309
310 private static boolean _isDeleteable(
311 Layout layout, ThemeDisplay themeDisplay)
312 throws PortalException {
313
314 if (!LayoutPermissionUtil.contains(
315 themeDisplay.getPermissionChecker(), layout,
316 ActionKeys.DELETE)) {
317
318 return false;
319 }
320
321 Group group = layout.getGroup();
322
323 if (group.isGuest() && !layout.isPrivateLayout() &&
324 layout.isRootLayout() &&
325 (LayoutLocalServiceUtil.getLayoutsCount(
326 group, false, LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) == 1)) {
327
328 return false;
329 }
330
331 return true;
332 }
333
334 private static boolean _isExpandableLayout(
335 HttpServletRequest request, List<Layout> ancestorLayouts,
336 long[] expandedLayoutIds, Layout layout) {
337
338 boolean expandParentLayouts = ParamUtil.getBoolean(
339 request, "expandParentLayouts");
340
341 if (expandParentLayouts || ancestorLayouts.contains(layout) ||
342 ArrayUtil.contains(expandedLayoutIds, layout.getLayoutId())) {
343
344 return true;
345 }
346
347 return false;
348 }
349
350 private static boolean _isPaginationEnabled(HttpServletRequest request) {
351 boolean paginate = ParamUtil.getBoolean(request, "paginate", true);
352
353 if (paginate &&
354 (PropsValues.LAYOUT_MANAGE_PAGES_INITIAL_CHILDREN > -1)) {
355
356 return true;
357 }
358
359 return false;
360 }
361
362 private static List<Layout> _paginateLayouts(
363 HttpServletRequest request, long groupId, boolean privateLayout,
364 long parentLayoutId, List<Layout> layouts, String treeId)
365 throws Exception {
366
367 if (!_isPaginationEnabled(request)) {
368 return layouts;
369 }
370
371 HttpSession session = request.getSession();
372
373 int loadedLayoutsCount = _getLoadedLayoutsCount(
374 session, groupId, privateLayout, parentLayoutId, treeId);
375
376 int start = ParamUtil.getInteger(request, "start");
377
378 start = Math.max(0, Math.min(start, layouts.size()));
379
380 int end = ParamUtil.getInteger(
381 request, "end",
382 start + PropsValues.LAYOUT_MANAGE_PAGES_INITIAL_CHILDREN);
383
384 if (loadedLayoutsCount > end) {
385 end = loadedLayoutsCount;
386 }
387
388 end = Math.max(start, Math.min(end, layouts.size()));
389
390 if (_log.isDebugEnabled()) {
391 StringBundler sb = new StringBundler(7);
392
393 sb.append("_paginateLayouts(loadedLayoutsCount=");
394 sb.append(loadedLayoutsCount);
395 sb.append(", start=");
396 sb.append(start);
397 sb.append(", end=");
398 sb.append(end);
399 sb.append(StringPool.CLOSE_PARENTHESIS);
400
401 _log.debug(sb.toString());
402 }
403
404 return layouts.subList(start, end);
405 }
406
407 private static String _toJSON(
408 HttpServletRequest request, long groupId,
409 LayoutTreeNodes layoutTreeNodes)
410 throws Exception {
411
412 if (_log.isDebugEnabled()) {
413 StringBundler sb = new StringBundler(5);
414
415 sb.append("_toJSON(groupId=");
416 sb.append(groupId);
417 sb.append(", layoutTreeNodes=");
418 sb.append(layoutTreeNodes);
419 sb.append(StringPool.CLOSE_PARENTHESIS);
420
421 _log.debug(sb.toString());
422 }
423
424 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
425 WebKeys.THEME_DISPLAY);
426
427 JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
428
429 boolean hasManageLayoutsPermission = GroupPermissionUtil.contains(
430 themeDisplay.getPermissionChecker(), groupId,
431 ActionKeys.MANAGE_LAYOUTS);
432
433 for (LayoutTreeNode layoutTreeNode : layoutTreeNodes) {
434 JSONObject jsonObject = JSONFactoryUtil.createJSONObject();
435
436 String childrenJSON = _toJSON(
437 request, groupId, layoutTreeNode.getChildLayoutTreeNodes());
438
439 jsonObject.put(
440 "children", JSONFactoryUtil.createJSONObject(childrenJSON));
441
442 Layout layout = layoutTreeNode.getLayout();
443
444 jsonObject.put("contentDisplayPage", layout.isContentDisplayPage());
445 jsonObject.put("deleteable", _isDeleteable(layout, themeDisplay));
446 jsonObject.put("friendlyURL", layout.getFriendlyURL());
447
448 if (layout instanceof VirtualLayout) {
449 VirtualLayout virtualLayout = (VirtualLayout)layout;
450
451 jsonObject.put("groupId", virtualLayout.getSourceGroupId());
452 }
453 else {
454 jsonObject.put("groupId", layout.getGroupId());
455 }
456
457 jsonObject.put("hasChildren", layout.hasChildren());
458 jsonObject.put("layoutId", layout.getLayoutId());
459 jsonObject.put("name", layout.getName(themeDisplay.getLocale()));
460 jsonObject.put(
461 "parentable",
462 LayoutPermissionUtil.contains(
463 themeDisplay.getPermissionChecker(), layout,
464 ActionKeys.ADD_LAYOUT));
465 jsonObject.put("parentLayoutId", layout.getParentLayoutId());
466 jsonObject.put("plid", layout.getPlid());
467 jsonObject.put("priority", layout.getPriority());
468 jsonObject.put("privateLayout", layout.isPrivateLayout());
469 jsonObject.put("regularURL", layout.getRegularURL(request));
470 jsonObject.put(
471 "sortable",
472 hasManageLayoutsPermission &&
473 SitesUtil.isLayoutSortable(layout));
474 jsonObject.put("type", layout.getType());
475 jsonObject.put(
476 "updateable",
477 LayoutPermissionUtil.contains(
478 themeDisplay.getPermissionChecker(), layout,
479 ActionKeys.UPDATE));
480 jsonObject.put("uuid", layout.getUuid());
481
482 LayoutRevision layoutRevision = LayoutStagingUtil.getLayoutRevision(
483 layout);
484
485 if (layoutRevision != null) {
486 long layoutSetBranchId = layoutRevision.getLayoutSetBranchId();
487
488 if (StagingUtil.isIncomplete(layout, layoutSetBranchId)) {
489 jsonObject.put("incomplete", true);
490 }
491
492 LayoutSetBranch layoutSetBranch =
493 LayoutSetBranchLocalServiceUtil.getLayoutSetBranch(
494 layoutSetBranchId);
495
496 LayoutBranch layoutBranch = layoutRevision.getLayoutBranch();
497
498 if (!layoutBranch.isMaster()) {
499 jsonObject.put(
500 "layoutBranchId", layoutBranch.getLayoutBranchId());
501 jsonObject.put("layoutBranchName", layoutBranch.getName());
502 }
503
504 if (layoutRevision.isHead()) {
505 jsonObject.put("layoutRevisionHead", true);
506 }
507
508 jsonObject.put(
509 "layoutRevisionId", layoutRevision.getLayoutRevisionId());
510 jsonObject.put("layoutSetBranchId", layoutSetBranchId);
511 jsonObject.put(
512 "layoutSetBranchName", layoutSetBranch.getName());
513 }
514
515 jsonArray.put(jsonObject);
516 }
517
518 JSONObject responseJSONObject = JSONFactoryUtil.createJSONObject();
519
520 responseJSONObject.put("layouts", jsonArray);
521 responseJSONObject.put("total", layoutTreeNodes.getTotal());
522
523 return responseJSONObject.toString();
524 }
525
526 private static final Log _log = LogFactoryUtil.getLog(
527 LayoutsTreeUtil.class);
528
529 private static class LayoutTreeNode {
530
531 public LayoutTreeNode(Layout layout) {
532 _layout = layout;
533 }
534
535 public LayoutTreeNodes getChildLayoutTreeNodes() {
536 return _childLayoutTreeNodes;
537 }
538
539 public Layout getLayout() {
540 return _layout;
541 }
542
543 public void setChildLayoutTreeNodes(
544 LayoutTreeNodes childLayoutTreeNodes) {
545
546 _childLayoutTreeNodes = childLayoutTreeNodes;
547 }
548
549 @Override
550 public String toString() {
551 StringBundler sb = new StringBundler(5);
552
553 sb.append("{childLayoutTreeNodes=");
554 sb.append(_childLayoutTreeNodes);
555 sb.append(", layout=");
556 sb.append(_layout);
557 sb.append(StringPool.CLOSE_CURLY_BRACE);
558
559 return sb.toString();
560 }
561
562 private LayoutTreeNodes _childLayoutTreeNodes = new LayoutTreeNodes();
563 private final Layout _layout;
564
565 }
566
567 private static class LayoutTreeNodes implements Iterable<LayoutTreeNode> {
568
569 public LayoutTreeNodes() {
570 _layoutTreeNodesList = new ArrayList<>();
571 }
572
573 public LayoutTreeNodes(
574 List<LayoutTreeNode> layoutTreeNodesList, int total) {
575
576 _layoutTreeNodesList = layoutTreeNodesList;
577 _total = total;
578 }
579
580 public void addAll(LayoutTreeNodes layoutTreeNodes) {
581 _layoutTreeNodesList.addAll(
582 layoutTreeNodes.getLayoutTreeNodesList());
583
584 _total += layoutTreeNodes.getTotal();
585 }
586
587 public List<LayoutTreeNode> getLayoutTreeNodesList() {
588 return _layoutTreeNodesList;
589 }
590
591 public int getTotal() {
592 return _total;
593 }
594
595 @Override
596 public Iterator<LayoutTreeNode> iterator() {
597 return _layoutTreeNodesList.iterator();
598 }
599
600 @Override
601 public String toString() {
602 StringBundler sb = new StringBundler(5);
603
604 sb.append("{layoutTreeNodesList=");
605 sb.append(_layoutTreeNodesList);
606 sb.append(", total=");
607 sb.append(_total);
608 sb.append(StringPool.CLOSE_CURLY_BRACE);
609
610 return sb.toString();
611 }
612
613 private final List<LayoutTreeNode> _layoutTreeNodesList;
614 private int _total;
615
616 }
617
618 }