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