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