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