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("regularURL", layout.getRegularURL(request));
431 jsonObject.put(
432 "sortable",
433 hasManageLayoutsPermission &&
434 SitesUtil.isLayoutSortable(layout));
435 jsonObject.put("type", layout.getType());
436 jsonObject.put(
437 "updateable",
438 LayoutPermissionUtil.contains(
439 themeDisplay.getPermissionChecker(), layout,
440 ActionKeys.UPDATE));
441 jsonObject.put("uuid", layout.getUuid());
442
443 LayoutRevision layoutRevision = LayoutStagingUtil.getLayoutRevision(
444 layout);
445
446 if (layoutRevision != null) {
447 User user = themeDisplay.getUser();
448
449 long recentLayoutSetBranchId =
450 StagingUtil.getRecentLayoutSetBranchId(
451 user, layout.getLayoutSet().getLayoutSetId());
452
453 if (StagingUtil.isIncomplete(layout, recentLayoutSetBranchId)) {
454 jsonObject.put("incomplete", true);
455 }
456
457 long layoutSetBranchId = layoutRevision.getLayoutSetBranchId();
458
459 LayoutSetBranch layoutSetBranch =
460 LayoutSetBranchLocalServiceUtil.getLayoutSetBranch(
461 layoutSetBranchId);
462
463 LayoutBranch layoutBranch = layoutRevision.getLayoutBranch();
464
465 if (!layoutBranch.isMaster()) {
466 jsonObject.put(
467 "layoutBranchId", layoutBranch.getLayoutBranchId());
468 jsonObject.put("layoutBranchName", layoutBranch.getName());
469 }
470
471 if (layoutRevision.isHead()) {
472 jsonObject.put("layoutRevisionHead", true);
473 }
474
475 jsonObject.put(
476 "layoutRevisionId", layoutRevision.getLayoutRevisionId());
477 jsonObject.put("layoutSetBranchId", layoutSetBranchId);
478 jsonObject.put(
479 "layoutSetBranchName", layoutSetBranch.getName());
480 }
481
482 jsonArray.put(jsonObject);
483 }
484
485 JSONObject responseJSONObject = JSONFactoryUtil.createJSONObject();
486
487 responseJSONObject.put("layouts", jsonArray);
488 responseJSONObject.put("total", layoutTreeNodes.getTotal());
489
490 return responseJSONObject.toString();
491 }
492
493 private static final Log _log = LogFactoryUtil.getLog(
494 LayoutsTreeUtil.class);
495
496 private static class LayoutTreeNode {
497
498 public LayoutTreeNode(Layout layout) {
499 _layout = layout;
500 }
501
502 public LayoutTreeNodes getChildLayoutTreeNodes() {
503 return _childLayoutTreeNodes;
504 }
505
506 public Layout getLayout() {
507 return _layout;
508 }
509
510 public void setChildLayoutTreeNodes(
511 LayoutTreeNodes childLayoutTreeNodes) {
512
513 _childLayoutTreeNodes = childLayoutTreeNodes;
514 }
515
516 @Override
517 public String toString() {
518 StringBundler sb = new StringBundler(5);
519
520 sb.append("{childLayoutTreeNodes=");
521 sb.append(_childLayoutTreeNodes);
522 sb.append(", layout=");
523 sb.append(_layout);
524 sb.append(StringPool.CLOSE_CURLY_BRACE);
525
526 return sb.toString();
527 }
528
529 private LayoutTreeNodes _childLayoutTreeNodes = new LayoutTreeNodes();
530 private final Layout _layout;
531
532 }
533
534 private static class LayoutTreeNodes implements Iterable<LayoutTreeNode> {
535
536 public LayoutTreeNodes() {
537 _layoutTreeNodesList = new ArrayList<>();
538 }
539
540 public LayoutTreeNodes(
541 List<LayoutTreeNode> layoutTreeNodesList, int total) {
542
543 _layoutTreeNodesList = layoutTreeNodesList;
544 _total = total;
545 }
546
547 public void addAll(LayoutTreeNodes layoutTreeNodes) {
548 _layoutTreeNodesList.addAll(
549 layoutTreeNodes.getLayoutTreeNodesList());
550
551 _total += layoutTreeNodes.getTotal();
552 }
553
554 public List<LayoutTreeNode> getLayoutTreeNodesList() {
555 return _layoutTreeNodesList;
556 }
557
558 public int getTotal() {
559 return _total;
560 }
561
562 @Override
563 public Iterator<LayoutTreeNode> iterator() {
564 return _layoutTreeNodesList.iterator();
565 }
566
567 @Override
568 public String toString() {
569 StringBundler sb = new StringBundler(5);
570
571 sb.append("{layoutTreeNodesList=");
572 sb.append(_layoutTreeNodesList);
573 sb.append(", total=");
574 sb.append(_total);
575 sb.append(StringPool.CLOSE_CURLY_BRACE);
576
577 return sb.toString();
578 }
579
580 private final List<LayoutTreeNode> _layoutTreeNodesList;
581 private int _total;
582
583 }
584
585 }