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