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