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.exception.SystemException;
019 import com.liferay.portal.kernel.json.JSONArray;
020 import com.liferay.portal.kernel.json.JSONFactoryUtil;
021 import com.liferay.portal.kernel.json.JSONObject;
022 import com.liferay.portal.kernel.staging.LayoutStagingUtil;
023 import com.liferay.portal.kernel.staging.StagingUtil;
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.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.PortalUtil;
044 import com.liferay.portal.util.PropsValues;
045 import com.liferay.portal.util.SessionClicks;
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 import java.util.Locale;
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 layoutId, int max)
080 throws Exception {
081
082 Layout layout = LayoutLocalServiceUtil.getLayout(
083 groupId, privateLayout, layoutId);
084
085 long parentLayoutId = layout.getParentLayoutId();
086
087 long includedLayoutIndex = LayoutServiceUtil.getLayoutsCount(
088 groupId, privateLayout, parentLayoutId, layout.getPriority());
089
090 int total = LayoutServiceUtil.getLayoutsCount(
091 groupId, privateLayout, parentLayoutId);
092
093 int start = (int)includedLayoutIndex - 1;
094 int end = (int)includedLayoutIndex + max;
095
096 if (end > total) {
097 start = total - max;
098 end = total;
099
100 if (start < 0) {
101 start = 0;
102 }
103 }
104
105 List<Layout> layouts = LayoutServiceUtil.getLayouts(
106 groupId, privateLayout, parentLayoutId, true, start, end);
107
108 JSONObject jsonObject = _toJSONObject(request, groupId, layouts, total);
109
110 List<Layout> ancestorLayouts = LayoutServiceUtil.getAncestorLayouts(
111 layout.getPlid());
112
113 long[] ancestorLayoutIds = new long[ancestorLayouts.size()];
114 String[] ancestorLayoutNames = new String[ancestorLayouts.size()];
115
116 Locale locale = PortalUtil.getLocale(request);
117
118 for (int i = 0; i < ancestorLayouts.size(); i++) {
119 Layout ancestorLayout = ancestorLayouts.get(i);
120
121 ancestorLayoutIds[i] = ancestorLayout.getLayoutId();
122 ancestorLayoutNames[i] = ancestorLayout.getName(locale);
123 }
124
125 jsonObject.put("ancestorLayoutIds", ancestorLayoutIds);
126 jsonObject.put("ancestorLayoutNames", ancestorLayoutNames);
127
128 jsonObject.put("start", start);
129
130 return jsonObject.toString();
131 }
132
133 public static String getLayoutsJSON(
134 HttpServletRequest request, long groupId, boolean privateLayout,
135 long parentLayoutId, long[] expandedLayoutIds, boolean incomplete,
136 String treeId)
137 throws Exception {
138
139 LayoutTreeNodes layoutTreeNodes = _getLayoutTreeNodes(
140 request, groupId, privateLayout, parentLayoutId, incomplete,
141 expandedLayoutIds, treeId);
142
143 return _toJSON(request, groupId, layoutTreeNodes);
144 }
145
146 public static String getLayoutsJSON(
147 HttpServletRequest request, long groupId, String treeId)
148 throws Exception {
149
150 LayoutTreeNodes layoutTreeNodes = new LayoutTreeNodes();
151
152 layoutTreeNodes.addAll(
153 _getLayoutTreeNodes(
154 request, groupId, true,
155 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID, false, null, treeId));
156 layoutTreeNodes.addAll(
157 _getLayoutTreeNodes(
158 request, groupId, false,
159 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID, false, null, treeId));
160
161 return _toJSON(request, groupId, layoutTreeNodes);
162 }
163
164 private static Layout _fetchCurrentLayout(HttpServletRequest request)
165 throws SystemException {
166
167 long selPlid = ParamUtil.getLong(request, "selPlid");
168
169 if (selPlid > 0) {
170 return LayoutLocalServiceUtil.fetchLayout(selPlid);
171 }
172
173 ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
174 WebKeys.THEME_DISPLAY);
175
176 Layout layout = themeDisplay.getLayout();
177
178 if (!layout.isTypeControlPanel()) {
179 return layout;
180 }
181
182 return null;
183 }
184
185 private static JSONObject _toJSONObject(
186 HttpServletRequest request, long groupId, List<Layout> layouts,
187 int total)
188 throws Exception {
189
190 List<LayoutTreeNode> layoutTreeNodesList =
191 new ArrayList<LayoutTreeNode>();
192
193 for (Layout layout : layouts) {
194 LayoutTreeNode layoutTreeNode = new LayoutTreeNode(layout);
195
196 layoutTreeNodesList.add(layoutTreeNode);
197 }
198
199 LayoutTreeNodes layoutTreeNodes = new LayoutTreeNodes(
200 layoutTreeNodesList, total);
201
202 return _toJSONObject(request, groupId, layoutTreeNodes);
203 }
204
205 private static List<Layout> _getAncestorLayouts(HttpServletRequest request)
206 throws Exception {
207
208 long selPlid = ParamUtil.getLong(request, "selPlid");
209
210 if (selPlid == 0) {
211 return Collections.emptyList();
212 }
213
214 List<Layout> ancestorLayouts = LayoutServiceUtil.getAncestorLayouts(
215 selPlid);
216
217 Layout layout = LayoutLocalServiceUtil.getLayout(selPlid);
218
219 ancestorLayouts.add(layout);
220
221 return ancestorLayouts;
222 }
223
224 private static LayoutTreeNodes _getLayoutTreeNodes(
225 HttpServletRequest request, long groupId, boolean privateLayout,
226 long parentLayoutId, boolean incomplete, long[] expandedLayoutIds,
227 String treeId)
228 throws Exception {
229
230 List<LayoutTreeNode> layoutTreeNodes = new ArrayList<LayoutTreeNode>();
231
232 List<Layout> ancestorLayouts = _getAncestorLayouts(request);
233
234 List<Layout> layouts = LayoutServiceUtil.getLayouts(
235 groupId, privateLayout, parentLayoutId, incomplete,
236 QueryUtil.ALL_POS, QueryUtil.ALL_POS);
237
238 for (Layout layout :
239 _paginateLayouts(
240 request, groupId, privateLayout, parentLayoutId, layouts,
241 treeId)) {
242
243 LayoutTreeNode layoutTreeNode = new LayoutTreeNode(layout);
244
245 LayoutTreeNodes childLayoutTreeNodes = null;
246
247 if (_isExpandableLayout(
248 request, ancestorLayouts, expandedLayoutIds, layout)) {
249
250 if (layout instanceof VirtualLayout) {
251 VirtualLayout virtualLayout = (VirtualLayout)layout;
252
253 childLayoutTreeNodes = _getLayoutTreeNodes(
254 request, virtualLayout.getSourceGroupId(),
255 virtualLayout.isPrivateLayout(),
256 virtualLayout.getLayoutId(), incomplete,
257 expandedLayoutIds, treeId);
258 }
259 else {
260 childLayoutTreeNodes = _getLayoutTreeNodes(
261 request, groupId, layout.isPrivateLayout(),
262 layout.getLayoutId(), incomplete, expandedLayoutIds,
263 treeId);
264 }
265 }
266 else {
267 int childLayoutsCount = LayoutServiceUtil.getLayoutsCount(
268 groupId, privateLayout, layout.getLayoutId());
269
270 childLayoutTreeNodes = new LayoutTreeNodes(
271 new ArrayList<LayoutTreeNode>(), childLayoutsCount);
272 }
273
274 layoutTreeNode.setChildLayoutTreeNodes(childLayoutTreeNodes);
275
276 layoutTreeNodes.add(layoutTreeNode);
277 }
278
279 return new LayoutTreeNodes(layoutTreeNodes, layouts.size());
280 }
281
282 private static int _getLoadedLayoutsCount(
283 HttpSession session, long groupId, boolean privateLayout,
284 long layoutId, String treeId)
285 throws Exception {
286
287 StringBundler sb = new StringBundler(7);
288
289 sb.append(treeId);
290 sb.append(StringPool.COLON);
291 sb.append(groupId);
292 sb.append(StringPool.COLON);
293 sb.append(privateLayout);
294 sb.append(StringPool.COLON);
295 sb.append("Pagination");
296
297 String paginationJSON = SessionClicks.get(
298 session, sb.toString(), JSONFactoryUtil.getNullJSON());
299
300 JSONObject paginationJSONObject = JSONFactoryUtil.createJSONObject(
301 paginationJSON);
302
303 return paginationJSONObject.getInt(String.valueOf(layoutId), 0);
304 }
305
306 private static boolean _isExpandableLayout(
307 HttpServletRequest request, List<Layout> ancestorLayouts,
308 long[] expandedLayoutIds, Layout layout) {
309
310 boolean expandParentLayouts = ParamUtil.getBoolean(
311 request, "expandParentLayouts");
312
313 if (expandParentLayouts || ancestorLayouts.contains(layout) ||
314 ArrayUtil.contains(expandedLayoutIds, layout.getLayoutId())) {
315
316 return true;
317 }
318
319 return false;
320 }
321
322 private static boolean _isPaginationEnabled(HttpServletRequest request) {
323 boolean paginate = ParamUtil.getBoolean(request, "paginate", true);
324
325 if (paginate &&
326 (PropsValues.LAYOUT_MANAGE_PAGES_INITIAL_CHILDREN > -1)) {
327
328 return true;
329 }
330
331 return false;
332 }
333
334 private static List<Layout> _paginateLayouts(
335 HttpServletRequest request, long groupId, boolean privateLayout,
336 long parentLayoutId, List<Layout> layouts, String treeId)
337 throws Exception {
338
339 if (!_isPaginationEnabled(request)) {
340 return layouts;
341 }
342
343 HttpSession session = request.getSession();
344
345 int loadedLayoutsCount = _getLoadedLayoutsCount(
346 session, groupId, privateLayout, parentLayoutId, treeId);
347
348 int start = ParamUtil.getInteger(request, "start");
349
350 start = Math.max(0, Math.min(start, layouts.size()));
351
352 int end = ParamUtil.getInteger(
353 request, "end",
354 start + PropsValues.LAYOUT_MANAGE_PAGES_INITIAL_CHILDREN);
355
356 if (loadedLayoutsCount > end) {
357 end = loadedLayoutsCount;
358 }
359
360 end = Math.max(start, Math.min(end, layouts.size()));
361
362 return layouts.subList(start, end);
363 }
364
365 private static String _toJSON(
366 HttpServletRequest request, long groupId,
367 LayoutTreeNodes layoutTreeNodes)
368 throws Exception {
369
370 JSONObject jsonObject = _toJSONObject(
371 request, groupId, layoutTreeNodes);
372
373 return jsonObject.toString();
374 }
375
376 private static JSONObject _toJSONObject(
377 HttpServletRequest request, long groupId,
378 LayoutTreeNodes layoutTreeNodes)
379 throws Exception {
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 JSONObject childrenJSONObject = _toJSONObject(
394 request, groupId, layoutTreeNode.getChildLayoutTreeNodes());
395
396 jsonObject.put("children", childrenJSONObject);
397
398 Layout layout = layoutTreeNode.getLayout();
399
400 jsonObject.put("contentDisplayPage", layout.isContentDisplayPage());
401 jsonObject.put("friendlyURL", layout.getFriendlyURL());
402
403 if (layout instanceof VirtualLayout) {
404 VirtualLayout virtualLayout = (VirtualLayout)layout;
405
406 jsonObject.put("groupId", virtualLayout.getSourceGroupId());
407 }
408 else {
409 jsonObject.put("groupId", layout.getGroupId());
410 }
411
412 jsonObject.put("hasChildren", layout.hasChildren());
413 jsonObject.put("layoutId", layout.getLayoutId());
414 jsonObject.put("name", layout.getName(themeDisplay.getLocale()));
415 jsonObject.put("parentable", PortalUtil.isLayoutParentable(layout));
416 jsonObject.put("parentLayoutId", layout.getParentLayoutId());
417 jsonObject.put("plid", layout.getPlid());
418 jsonObject.put("priority", layout.getPriority());
419 jsonObject.put("privateLayout", layout.isPrivateLayout());
420 jsonObject.put(
421 "sortable",
422 hasManageLayoutsPermission &&
423 SitesUtil.isLayoutSortable(layout));
424 jsonObject.put("type", layout.getType());
425 jsonObject.put(
426 "updateable",
427 LayoutPermissionUtil.contains(
428 themeDisplay.getPermissionChecker(), layout,
429 ActionKeys.UPDATE));
430 jsonObject.put("uuid", layout.getUuid());
431
432 LayoutRevision layoutRevision = LayoutStagingUtil.getLayoutRevision(
433 layout);
434
435 if (layoutRevision != null) {
436 User user = themeDisplay.getUser();
437
438 long recentLayoutSetBranchId =
439 StagingUtil.getRecentLayoutSetBranchId(
440 user, layout.getLayoutSet().getLayoutSetId());
441
442 if (StagingUtil.isIncomplete(layout, recentLayoutSetBranchId)) {
443 jsonObject.put("incomplete", true);
444 }
445
446 long layoutSetBranchId = layoutRevision.getLayoutSetBranchId();
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;
480 }
481
482 private static class LayoutTreeNode {
483
484 public LayoutTreeNode(Layout layout) {
485 _layout = layout;
486 }
487
488 public Layout getLayout() {
489 return _layout;
490 }
491
492 public LayoutTreeNodes getChildLayoutTreeNodes() {
493 return _childLayoutTreeNodes;
494 }
495
496 public void setChildLayoutTreeNodes(
497 LayoutTreeNodes childLayoutTreeNodes) {
498
499 _childLayoutTreeNodes = childLayoutTreeNodes;
500 }
501
502 private LayoutTreeNodes _childLayoutTreeNodes = new LayoutTreeNodes();
503 private Layout _layout;
504
505 }
506
507 private static class LayoutTreeNodes implements Iterable<LayoutTreeNode> {
508
509 public LayoutTreeNodes() {
510 }
511
512 public LayoutTreeNodes(
513 List<LayoutTreeNode> layoutTreeNodesList, int total) {
514
515 _layoutTreeNodesList = layoutTreeNodesList;
516 _total = total;
517 }
518
519 public void addAll(LayoutTreeNodes layoutTreeNodes) {
520 _layoutTreeNodesList.addAll(
521 layoutTreeNodes.getLayoutTreeNodesList());
522
523 _total += layoutTreeNodes.getTotal();
524 }
525
526 public int getTotal() {
527 return _total;
528 }
529
530 public List<LayoutTreeNode> getLayoutTreeNodesList() {
531 return _layoutTreeNodesList;
532 }
533
534 @Override
535 public Iterator<LayoutTreeNode> iterator() {
536 return _layoutTreeNodesList.iterator();
537 }
538
539 private List<LayoutTreeNode> _layoutTreeNodesList =
540 new ArrayList<LayoutTreeNode>();
541 private int _total;
542
543 }
544
545 }