001
014
015 package com.liferay.portal.service.impl;
016
017 import com.liferay.portal.LayoutFriendlyURLException;
018 import com.liferay.portal.LayoutFriendlyURLsException;
019 import com.liferay.portal.LayoutNameException;
020 import com.liferay.portal.LayoutParentLayoutIdException;
021 import com.liferay.portal.LayoutTypeException;
022 import com.liferay.portal.NoSuchLayoutException;
023 import com.liferay.portal.kernel.bean.BeanReference;
024 import com.liferay.portal.kernel.bean.IdentifiableBean;
025 import com.liferay.portal.kernel.exception.PortalException;
026 import com.liferay.portal.kernel.language.LanguageUtil;
027 import com.liferay.portal.kernel.portlet.FriendlyURLMapper;
028 import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
029 import com.liferay.portal.kernel.util.LocaleUtil;
030 import com.liferay.portal.kernel.util.StringPool;
031 import com.liferay.portal.kernel.util.StringUtil;
032 import com.liferay.portal.kernel.util.Validator;
033 import com.liferay.portal.model.Group;
034 import com.liferay.portal.model.Layout;
035 import com.liferay.portal.model.LayoutConstants;
036 import com.liferay.portal.model.LayoutFriendlyURL;
037 import com.liferay.portal.model.LayoutSet;
038 import com.liferay.portal.model.LayoutSetPrototype;
039 import com.liferay.portal.model.LayoutType;
040 import com.liferay.portal.model.LayoutTypeController;
041 import com.liferay.portal.model.ResourceConstants;
042 import com.liferay.portal.model.Role;
043 import com.liferay.portal.model.RoleConstants;
044 import com.liferay.portal.model.impl.LayoutImpl;
045 import com.liferay.portal.security.permission.ActionKeys;
046 import com.liferay.portal.service.PortletLocalServiceUtil;
047 import com.liferay.portal.service.ResourcePermissionLocalService;
048 import com.liferay.portal.service.RoleLocalServiceUtil;
049 import com.liferay.portal.service.persistence.LayoutFriendlyURLPersistence;
050 import com.liferay.portal.service.persistence.LayoutPersistence;
051 import com.liferay.portal.service.persistence.LayoutSetPersistence;
052 import com.liferay.portal.util.LayoutTypeControllerTracker;
053 import com.liferay.portal.util.Portal;
054 import com.liferay.portal.util.PortalUtil;
055 import com.liferay.portal.util.comparator.LayoutPriorityComparator;
056 import com.liferay.portlet.sites.util.SitesUtil;
057
058 import java.util.HashMap;
059 import java.util.List;
060 import java.util.Locale;
061 import java.util.Map;
062
063
066 public class LayoutLocalServiceHelper implements IdentifiableBean {
067
068 @Override
069 public String getBeanIdentifier() {
070 return _beanIdentifier;
071 }
072
073 public String getFriendlyURL(
074 long groupId, boolean privateLayout, long layoutId, String name,
075 String friendlyURL)
076 throws PortalException {
077
078 friendlyURL = getFriendlyURL(friendlyURL);
079
080 if (Validator.isNotNull(friendlyURL)) {
081 return friendlyURL;
082 }
083
084 friendlyURL = StringPool.SLASH + getFriendlyURL(name);
085
086 String originalFriendlyURL = friendlyURL;
087
088 for (int i = 1;; i++) {
089 try {
090 validateFriendlyURL(
091 groupId, privateLayout, layoutId, friendlyURL);
092
093 break;
094 }
095 catch (LayoutFriendlyURLException lfurle) {
096 int type = lfurle.getType();
097
098 if (type == LayoutFriendlyURLException.DUPLICATE) {
099 friendlyURL = originalFriendlyURL + i;
100 }
101 else {
102 friendlyURL = StringPool.SLASH + layoutId;
103
104 break;
105 }
106 }
107 }
108
109 return friendlyURL;
110 }
111
112 public String getFriendlyURL(String friendlyURL) {
113 return FriendlyURLNormalizerUtil.normalize(friendlyURL);
114 }
115
116 public Map<Locale, String> getFriendlyURLMap(
117 long groupId, boolean privateLayout, long layoutId, String name,
118 Map<Locale, String> friendlyURLMap)
119 throws PortalException {
120
121 Map<Locale, String> newFriendlyURLMap = new HashMap<Locale, String>();
122
123 Locale[] locales = LanguageUtil.getAvailableLocales(groupId);
124
125 for (Locale locale : locales) {
126 String friendlyURL = friendlyURLMap.get(locale);
127
128 if (Validator.isNotNull(friendlyURL)) {
129 friendlyURL = getFriendlyURL(
130 groupId, privateLayout, layoutId, name, friendlyURL);
131
132 newFriendlyURLMap.put(locale, friendlyURL);
133 }
134 }
135
136 Locale siteDefaultLocale = LocaleUtil.getSiteDefault();
137
138 if (newFriendlyURLMap.isEmpty() ||
139 Validator.isNull(newFriendlyURLMap.get(siteDefaultLocale))) {
140
141 String friendlyURL = getFriendlyURL(
142 groupId, privateLayout, layoutId, name, StringPool.BLANK);
143
144 newFriendlyURLMap.put(siteDefaultLocale, friendlyURL);
145 }
146
147 return newFriendlyURLMap;
148 }
149
150 public int getNextPriority(
151 long groupId, boolean privateLayout, long parentLayoutId,
152 String sourcePrototypeLayoutUuid, int defaultPriority) {
153
154 try {
155 int priority = defaultPriority;
156
157 if (priority < 0) {
158 Layout layout = layoutPersistence.findByG_P_P_First(
159 groupId, privateLayout, parentLayoutId,
160 new LayoutPriorityComparator(false));
161
162 priority = layout.getPriority() + 1;
163 }
164
165 if ((priority < _PRIORITY_BUFFER) &&
166 Validator.isNull(sourcePrototypeLayoutUuid)) {
167
168 LayoutSet layoutSet = layoutSetPersistence.fetchByG_P(
169 groupId, privateLayout);
170
171 if (Validator.isNotNull(
172 layoutSet.getLayoutSetPrototypeUuid()) &&
173 layoutSet.isLayoutSetPrototypeLinkEnabled()) {
174
175 priority = priority + _PRIORITY_BUFFER;
176 }
177 }
178
179 return priority;
180 }
181 catch (NoSuchLayoutException nsle) {
182 return 0;
183 }
184 }
185
186 public long getParentLayoutId(
187 long groupId, boolean privateLayout, long parentLayoutId) {
188
189 if (parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
190
191
192
193 Layout parentLayout = layoutPersistence.fetchByG_P_L(
194 groupId, privateLayout, parentLayoutId);
195
196 if (parentLayout == null) {
197 parentLayoutId = LayoutConstants.DEFAULT_PARENT_LAYOUT_ID;
198 }
199 }
200
201 return parentLayoutId;
202 }
203
204 public boolean hasLayoutSetPrototypeLayout(
205 LayoutSetPrototype layoutSetPrototype, String layoutUuid)
206 throws PortalException {
207
208 Layout layout = layoutPersistence.fetchByUUID_G_P(
209 layoutUuid, layoutSetPrototype.getGroupId(), true);
210
211 if (layout != null) {
212 return true;
213 }
214
215 return false;
216 }
217
218 @Override
219 public void setBeanIdentifier(String beanIdentifier) {
220 _beanIdentifier = beanIdentifier;
221 }
222
223 public void validate(
224 long groupId, boolean privateLayout, long layoutId,
225 long parentLayoutId, String name, String type, boolean hidden,
226 Map<Locale, String> friendlyURLMap)
227 throws PortalException {
228
229 validateName(name);
230
231 boolean firstLayout = false;
232
233 if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
234 List<Layout> layouts = layoutPersistence.findByG_P_P(
235 groupId, privateLayout, parentLayoutId, 0, 1);
236
237 if (layouts.isEmpty()) {
238 firstLayout = true;
239 }
240 else {
241 long firstLayoutId = layouts.get(0).getLayoutId();
242
243 if (firstLayoutId == layoutId) {
244 firstLayout = true;
245 }
246 }
247 }
248 else {
249
250
251
252
253 Layout parentLayout = layoutPersistence.findByG_P_L(
254 groupId, privateLayout, parentLayoutId);
255
256 if (!SitesUtil.isLayoutSortable(parentLayout)) {
257 throw new LayoutParentLayoutIdException(
258 LayoutParentLayoutIdException.NOT_SORTABLE);
259 }
260 }
261
262 if (firstLayout) {
263 validateFirstLayout(type);
264 }
265
266 LayoutTypeController layoutTypeController =
267 LayoutTypeControllerTracker.getLayoutTypeController(type);
268
269 if (!layoutTypeController.isParentable()) {
270 if (layoutPersistence.countByG_P_P(
271 groupId, privateLayout, layoutId) > 0) {
272
273 throw new LayoutTypeException(
274 LayoutTypeException.NOT_PARENTABLE);
275 }
276 }
277
278 validateFriendlyURLs(groupId, privateLayout, layoutId, friendlyURLMap);
279 }
280
281 public void validateFirstLayout(Layout layout) throws PortalException {
282 Group group = layout.getGroup();
283
284 if (group.isGuest() && layout.isPublicLayout() &&
285 !hasGuestViewPermission(layout)) {
286
287 LayoutTypeException lte = new LayoutTypeException(
288 LayoutTypeException.FIRST_LAYOUT_PERMISSION);
289
290 throw lte;
291 }
292
293 validateFirstLayout(layout.getType());
294 }
295
296 public void validateFirstLayout(String type) throws PortalException {
297 LayoutTypeController layoutTypeController =
298 LayoutTypeControllerTracker.getLayoutTypeController(type);
299
300 if (Validator.isNull(type) || !layoutTypeController.isFirstPageable()) {
301 LayoutTypeException lte = new LayoutTypeException(
302 LayoutTypeException.FIRST_LAYOUT);
303
304 lte.setLayoutType(type);
305
306 throw lte;
307 }
308 }
309
310 public void validateFriendlyURL(
311 long groupId, boolean privateLayout, long layoutId,
312 String friendlyURL)
313 throws PortalException {
314
315 if (Validator.isNull(friendlyURL)) {
316 return;
317 }
318
319 int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
320
321 if (exceptionType != -1) {
322 throw new LayoutFriendlyURLException(exceptionType);
323 }
324
325 List<LayoutFriendlyURL> layoutFriendlyURLs =
326 layoutFriendlyURLPersistence.findByG_P_F(
327 groupId, privateLayout, friendlyURL);
328
329 for (LayoutFriendlyURL layoutFriendlyURL : layoutFriendlyURLs) {
330 Layout layout = layoutPersistence.findByPrimaryKey(
331 layoutFriendlyURL.getPlid());
332
333 if (layout.getLayoutId() != layoutId) {
334 LayoutFriendlyURLException lfurle =
335 new LayoutFriendlyURLException(
336 LayoutFriendlyURLException.DUPLICATE);
337
338 lfurle.setDuplicateClassPK(layout.getPlid());
339 lfurle.setDuplicateClassName(Layout.class.getName());
340
341 throw lfurle;
342 }
343 }
344
345 LayoutImpl.validateFriendlyURLKeyword(friendlyURL);
346
347 if (friendlyURL.contains(Portal.FRIENDLY_URL_SEPARATOR)) {
348 LayoutFriendlyURLException lfurle = new LayoutFriendlyURLException(
349 LayoutFriendlyURLException.KEYWORD_CONFLICT);
350
351 lfurle.setKeywordConflict(Portal.FRIENDLY_URL_SEPARATOR);
352
353 throw lfurle;
354 }
355
356 List<FriendlyURLMapper> friendlyURLMappers =
357 PortletLocalServiceUtil.getFriendlyURLMappers();
358
359 for (FriendlyURLMapper friendlyURLMapper : friendlyURLMappers) {
360 if (friendlyURLMapper.isCheckMappingWithPrefix()) {
361 continue;
362 }
363
364 String mapping = StringPool.SLASH + friendlyURLMapper.getMapping();
365
366 if (friendlyURL.contains(mapping + StringPool.SLASH) ||
367 friendlyURL.endsWith(mapping)) {
368
369 LayoutFriendlyURLException lfurle =
370 new LayoutFriendlyURLException(
371 LayoutFriendlyURLException.KEYWORD_CONFLICT);
372
373 lfurle.setKeywordConflict(friendlyURLMapper.getMapping());
374
375 throw lfurle;
376 }
377 }
378
379 Locale[] availableLocales = LanguageUtil.getAvailableLocales();
380
381 for (Locale locale : availableLocales) {
382 String languageId = StringUtil.toLowerCase(
383 LocaleUtil.toLanguageId(locale));
384
385 String i18nPathLanguageId =
386 StringPool.SLASH +
387 PortalUtil.getI18nPathLanguageId(locale, languageId);
388
389 if (friendlyURL.startsWith(i18nPathLanguageId + StringPool.SLASH) ||
390 friendlyURL.startsWith(
391 StringPool.SLASH + languageId + StringPool.SLASH) ||
392 friendlyURL.endsWith(i18nPathLanguageId) ||
393 friendlyURL.endsWith(StringPool.SLASH + languageId)) {
394
395 LayoutFriendlyURLException lfurle =
396 new LayoutFriendlyURLException(
397 LayoutFriendlyURLException.KEYWORD_CONFLICT);
398
399 lfurle.setKeywordConflict(i18nPathLanguageId);
400
401 throw lfurle;
402 }
403 }
404
405 String layoutIdFriendlyURL = friendlyURL.substring(1);
406
407 if (Validator.isNumber(layoutIdFriendlyURL) &&
408 !layoutIdFriendlyURL.equals(String.valueOf(layoutId))) {
409
410 LayoutFriendlyURLException lfurle = new LayoutFriendlyURLException(
411 LayoutFriendlyURLException.POSSIBLE_DUPLICATE);
412
413 lfurle.setKeywordConflict(layoutIdFriendlyURL);
414
415 throw lfurle;
416 }
417 }
418
419 public void validateFriendlyURLs(
420 long groupId, boolean privateLayout, long layoutId,
421 Map<Locale, String> friendlyURLMap)
422 throws PortalException {
423
424 LayoutFriendlyURLsException layoutFriendlyURLsException = null;
425
426 for (Map.Entry<Locale, String> entry : friendlyURLMap.entrySet()) {
427 try {
428 String friendlyURL = entry.getValue();
429
430 validateFriendlyURL(
431 groupId, privateLayout, layoutId, friendlyURL);
432 }
433 catch (LayoutFriendlyURLException lfurle) {
434 Locale locale = entry.getKey();
435
436 if (layoutFriendlyURLsException == null) {
437 layoutFriendlyURLsException =
438 new LayoutFriendlyURLsException(lfurle);
439 }
440 else {
441 layoutFriendlyURLsException.addSuppressed(lfurle);
442 }
443
444 layoutFriendlyURLsException.addLocalizedException(
445 locale, lfurle);
446 }
447 }
448
449 if (layoutFriendlyURLsException != null) {
450 throw layoutFriendlyURLsException;
451 }
452 }
453
454 public void validateName(String name) throws PortalException {
455 if (Validator.isNull(name)) {
456 throw new LayoutNameException();
457 }
458 }
459
460 public void validateName(String name, String languageId)
461 throws PortalException {
462
463 String defaultLanguageId = LocaleUtil.toLanguageId(
464 LocaleUtil.getSiteDefault());
465
466 if (defaultLanguageId.equals(languageId)) {
467 validateName(name);
468 }
469 }
470
471 public void validateParentLayoutId(
472 long groupId, boolean privateLayout, long layoutId,
473 long parentLayoutId)
474 throws PortalException {
475
476 Layout layout = layoutPersistence.findByG_P_L(
477 groupId, privateLayout, layoutId);
478
479 if (parentLayoutId == layout.getParentLayoutId()) {
480 return;
481 }
482
483
484
485 if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
486 return;
487 }
488
489
490
491 Layout parentLayout = layoutPersistence.findByG_P_L(
492 groupId, privateLayout, parentLayoutId);
493
494 LayoutType parentLayoutType = parentLayout.getLayoutType();
495
496 if (!parentLayoutType.isParentable()) {
497 throw new LayoutParentLayoutIdException(
498 LayoutParentLayoutIdException.NOT_PARENTABLE);
499 }
500
501
502
503
504 if (!SitesUtil.isLayoutSortable(parentLayout)) {
505 throw new LayoutParentLayoutIdException(
506 LayoutParentLayoutIdException.NOT_SORTABLE);
507 }
508
509
510
511 if (PortalUtil.isLayoutDescendant(layout, parentLayoutId)) {
512 throw new LayoutParentLayoutIdException(
513 LayoutParentLayoutIdException.SELF_DESCENDANT);
514 }
515
516
517
518 if (layout.getParentLayoutId() ==
519 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
520
521 List<Layout> layouts = layoutPersistence.findByG_P_P(
522 groupId, privateLayout,
523 LayoutConstants.DEFAULT_PARENT_LAYOUT_ID, 0, 2);
524
525
526
527
528 long firstLayoutId = layouts.get(0).getLayoutId();
529
530 if (firstLayoutId == layoutId) {
531 Layout secondLayout = layouts.get(1);
532
533 LayoutType layoutType = secondLayout.getLayoutType();
534
535 if (Validator.isNull(secondLayout.getType()) ||
536 !layoutType.isFirstPageable()) {
537
538 throw new LayoutParentLayoutIdException(
539 LayoutParentLayoutIdException.FIRST_LAYOUT_TYPE);
540 }
541 }
542 }
543 }
544
545 protected boolean hasGuestViewPermission(Layout layout)
546 throws PortalException {
547
548 Role role = RoleLocalServiceUtil.getRole(
549 layout.getCompanyId(), RoleConstants.GUEST);
550
551 return resourcePermissionLocalService.hasResourcePermission(
552 layout.getCompanyId(), Layout.class.getName(),
553 ResourceConstants.SCOPE_INDIVIDUAL,
554 String.valueOf(layout.getPlid()), role.getRoleId(),
555 ActionKeys.VIEW);
556 }
557
558 @BeanReference(type = LayoutFriendlyURLPersistence.class)
559 protected LayoutFriendlyURLPersistence layoutFriendlyURLPersistence;
560
561 @BeanReference(type = LayoutPersistence.class)
562 protected LayoutPersistence layoutPersistence;
563
564 @BeanReference(type = LayoutSetPersistence.class)
565 protected LayoutSetPersistence layoutSetPersistence;
566
567 @BeanReference(type = ResourcePermissionLocalService.class)
568 protected ResourcePermissionLocalService resourcePermissionLocalService;
569
570 private static final int _PRIORITY_BUFFER = 1000000;
571
572 private String _beanIdentifier;
573
574 }