001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.model.impl;
016    
017    import com.liferay.counter.kernel.service.CounterLocalServiceUtil;
018    import com.liferay.portal.kernel.configuration.Filter;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.exception.SystemException;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.model.CustomizedPages;
024    import com.liferay.portal.kernel.model.Group;
025    import com.liferay.portal.kernel.model.Layout;
026    import com.liferay.portal.kernel.model.LayoutSet;
027    import com.liferay.portal.kernel.model.LayoutTemplate;
028    import com.liferay.portal.kernel.model.LayoutTypeAccessPolicy;
029    import com.liferay.portal.kernel.model.LayoutTypeController;
030    import com.liferay.portal.kernel.model.LayoutTypePortlet;
031    import com.liferay.portal.kernel.model.LayoutTypePortletConstants;
032    import com.liferay.portal.kernel.model.Plugin;
033    import com.liferay.portal.kernel.model.Portlet;
034    import com.liferay.portal.kernel.model.PortletConstants;
035    import com.liferay.portal.kernel.model.PortletPreferencesIds;
036    import com.liferay.portal.kernel.model.ResourcePermission;
037    import com.liferay.portal.kernel.model.Theme;
038    import com.liferay.portal.kernel.portlet.PortalPreferences;
039    import com.liferay.portal.kernel.portlet.PortletLayoutListener;
040    import com.liferay.portal.kernel.portlet.PortletPreferencesFactoryUtil;
041    import com.liferay.portal.kernel.security.permission.ActionKeys;
042    import com.liferay.portal.kernel.security.permission.PermissionChecker;
043    import com.liferay.portal.kernel.security.permission.PermissionThreadLocal;
044    import com.liferay.portal.kernel.service.LayoutTemplateLocalServiceUtil;
045    import com.liferay.portal.kernel.service.PluginSettingLocalServiceUtil;
046    import com.liferay.portal.kernel.service.PortletLocalServiceUtil;
047    import com.liferay.portal.kernel.service.PortletPreferencesLocalServiceUtil;
048    import com.liferay.portal.kernel.service.ResourcePermissionLocalServiceUtil;
049    import com.liferay.portal.kernel.service.permission.LayoutPermissionUtil;
050    import com.liferay.portal.kernel.service.permission.PortletPermissionUtil;
051    import com.liferay.portal.kernel.util.ArrayUtil;
052    import com.liferay.portal.kernel.util.DateFormatFactoryUtil;
053    import com.liferay.portal.kernel.util.FastDateFormatFactoryUtil;
054    import com.liferay.portal.kernel.util.GetterUtil;
055    import com.liferay.portal.kernel.util.LayoutTypePortletFactoryUtil;
056    import com.liferay.portal.kernel.util.ListUtil;
057    import com.liferay.portal.kernel.util.PortalUtil;
058    import com.liferay.portal.kernel.util.PortletKeys;
059    import com.liferay.portal.kernel.util.PropsKeys;
060    import com.liferay.portal.kernel.util.StringPool;
061    import com.liferay.portal.kernel.util.StringUtil;
062    import com.liferay.portal.kernel.util.UnicodeProperties;
063    import com.liferay.portal.kernel.util.Validator;
064    import com.liferay.portal.util.PropsUtil;
065    import com.liferay.portal.util.PropsValues;
066    import com.liferay.sites.kernel.util.SitesUtil;
067    import com.liferay.util.JS;
068    
069    import java.text.DateFormat;
070    import java.text.Format;
071    
072    import java.util.ArrayList;
073    import java.util.Date;
074    import java.util.HashSet;
075    import java.util.List;
076    import java.util.Map;
077    import java.util.Set;
078    
079    /**
080     * @author Brian Wing Shun Chan
081     * @author Berentey Zsolt
082     * @author Jorge Ferrer
083     * @author Raymond Augé
084     */
085    public class LayoutTypePortletImpl
086            extends LayoutTypeImpl implements LayoutTypePortlet {
087    
088            public LayoutTypePortletImpl(
089                    Layout layout, LayoutTypeController layoutTypeController,
090                    LayoutTypeAccessPolicy layoutTypeAccessPolicy) {
091    
092                    super(layout, layoutTypeController, layoutTypeAccessPolicy);
093    
094                    _layoutSetPrototypeLayout = SitesUtil.getLayoutSetPrototypeLayout(
095                            layout);
096            }
097    
098            @Override
099            public void addModeAboutPortletId(String portletId) {
100                    removeModesPortletId(portletId);
101                    setModeAbout(StringUtil.add(getModeAbout(), portletId));
102            }
103    
104            @Override
105            public void addModeConfigPortletId(String portletId) {
106                    removeModesPortletId(portletId);
107                    setModeConfig(StringUtil.add(getModeConfig(), portletId));
108            }
109    
110            @Override
111            public void addModeEditDefaultsPortletId(String portletId) {
112                    removeModesPortletId(portletId);
113                    setModeEditDefaults(StringUtil.add(getModeEditDefaults(), portletId));
114            }
115    
116            @Override
117            public void addModeEditGuestPortletId(String portletId) {
118                    removeModesPortletId(portletId);
119                    setModeEditGuest(StringUtil.add(getModeEditGuest(), portletId));
120            }
121    
122            @Override
123            public void addModeEditPortletId(String portletId) {
124                    removeModesPortletId(portletId);
125                    setModeEdit(StringUtil.add(getModeEdit(), portletId));
126            }
127    
128            @Override
129            public void addModeHelpPortletId(String portletId) {
130                    removeModesPortletId(portletId);
131                    setModeHelp(StringUtil.add(getModeHelp(), portletId));
132            }
133    
134            @Override
135            public void addModePreviewPortletId(String portletId) {
136                    removeModesPortletId(portletId);
137                    setModePreview(StringUtil.add(getModePreview(), portletId));
138            }
139    
140            @Override
141            public void addModePrintPortletId(String portletId) {
142                    removeModesPortletId(portletId);
143                    setModePrint(StringUtil.add(getModePrint(), portletId));
144            }
145    
146            @Override
147            public String addPortletId(long userId, String portletId) {
148                    return addPortletId(userId, portletId, true);
149            }
150    
151            @Override
152            public String addPortletId(
153                    long userId, String portletId, boolean checkPermission) {
154    
155                    return addPortletId(userId, portletId, null, -1, checkPermission);
156            }
157    
158            @Override
159            public String addPortletId(
160                    long userId, String portletId, String columnId, int columnPos) {
161    
162                    return addPortletId(userId, portletId, columnId, columnPos, true);
163            }
164    
165            @Override
166            public String addPortletId(
167                    long userId, String portletId, String columnId, int columnPos,
168                    boolean checkPermission) {
169    
170                    return addPortletId(
171                            userId, portletId, columnId, columnPos, checkPermission, false);
172            }
173    
174            @Override
175            public void addPortletIds(
176                    long userId, String[] portletIds, boolean checkPermission) {
177    
178                    for (String portletId : portletIds) {
179                            addPortletId(userId, portletId, checkPermission);
180                    }
181            }
182    
183            @Override
184            public void addPortletIds(
185                    long userId, String[] portletIds, String columnId,
186                    boolean checkPermission) {
187    
188                    for (String portletId : portletIds) {
189                            addPortletId(userId, portletId, columnId, -1, checkPermission);
190                    }
191            }
192    
193            @Override
194            public void addStateMaxPortletId(String portletId) {
195                    removeStatesPortletId(portletId);
196                    //setStateMax(StringUtil.add(getStateMax(), portletId));
197                    setStateMax(StringUtil.add(StringPool.BLANK, portletId));
198            }
199    
200            @Override
201            public void addStateMinPortletId(String portletId) {
202                    removeStateMaxPortletId(portletId);
203                    setStateMin(StringUtil.add(getStateMin(), portletId));
204            }
205    
206            @Override
207            public List<Portlet> addStaticPortlets(
208                    List<Portlet> portlets, List<Portlet> startPortlets,
209                    List<Portlet> endPortlets) {
210    
211                    // Return the original array of portlets if no static portlets are
212                    // specified
213    
214                    if (startPortlets == null) {
215                            startPortlets = new ArrayList<>();
216                    }
217    
218                    if (endPortlets == null) {
219                            endPortlets = new ArrayList<>();
220                    }
221    
222                    if (startPortlets.isEmpty() && endPortlets.isEmpty()) {
223                            return portlets;
224                    }
225    
226                    // New array of portlets that contain the static portlets
227    
228                    List<Portlet> list = new ArrayList<>(
229                            portlets.size() + startPortlets.size() + endPortlets.size());
230    
231                    if (!startPortlets.isEmpty()) {
232                            list.addAll(startPortlets);
233                    }
234    
235                    for (int i = 0; i < portlets.size(); i++) {
236                            Portlet portlet = portlets.get(i);
237    
238                            // Add the portlet if and only if it is not also a static portlet
239    
240                            if (!startPortlets.contains(portlet) &&
241                                    !endPortlets.contains(portlet)) {
242    
243                                    list.add(portlet);
244                            }
245                    }
246    
247                    if (!endPortlets.isEmpty()) {
248                            list.addAll(endPortlets);
249                    }
250    
251                    return list;
252            }
253    
254            @Override
255            public List<Portlet> getAllPortlets() {
256                    List<Portlet> explicitlyAddedPortlets = getExplicitlyAddedPortlets();
257    
258                    List<Portlet> staticPortlets = getStaticPortlets(
259                            PropsKeys.LAYOUT_STATIC_PORTLETS_ALL);
260    
261                    List<Portlet> embeddedPortlets = getEmbeddedPortlets();
262    
263                    return addStaticPortlets(
264                            explicitlyAddedPortlets, staticPortlets, embeddedPortlets);
265            }
266    
267            @Override
268            public List<Portlet> getAllPortlets(boolean includeSystem) {
269                    List<Portlet> filteredPortlets = new ArrayList<>();
270    
271                    List<Portlet> portlets = getAllPortlets();
272    
273                    for (Portlet portlet : portlets) {
274                            if (portlet.isSystem() && !includeSystem) {
275                                    continue;
276                            }
277    
278                            filteredPortlets.add(portlet);
279                    }
280    
281                    return filteredPortlets;
282            }
283    
284            @Override
285            public List<Portlet> getAllPortlets(String columnId) {
286                    String columnValue = getColumnValue(columnId);
287    
288                    String[] portletIds = StringUtil.split(columnValue);
289    
290                    List<Portlet> portlets = new ArrayList<>(portletIds.length);
291    
292                    for (String portletId : portletIds) {
293                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
294                                    getCompanyId(), portletId);
295    
296                            if (portlet != null) {
297                                    portlets.add(portlet);
298                            }
299                    }
300    
301                    List<Portlet> startPortlets = getStaticPortlets(
302                            PropsKeys.LAYOUT_STATIC_PORTLETS_START + columnId);
303    
304                    List<Portlet> endPortlets = getStaticPortlets(
305                            PropsKeys.LAYOUT_STATIC_PORTLETS_END + columnId);
306    
307                    return addStaticPortlets(portlets, startPortlets, endPortlets);
308            }
309    
310            @Override
311            public List<Portlet> getEmbeddedPortlets() {
312                    Layout layout = getLayout();
313    
314                    return layout.getEmbeddedPortlets();
315            }
316    
317            @Override
318            public List<Portlet> getExplicitlyAddedPortlets() {
319                    List<Portlet> portlets = new ArrayList<>();
320    
321                    List<String> columns = getColumns();
322    
323                    for (int i = 0; i < columns.size(); i++) {
324                            String columnId = columns.get(i);
325    
326                            portlets.addAll(getAllPortlets(columnId));
327                    }
328    
329                    return portlets;
330            }
331    
332            @Override
333            public Layout getLayoutSetPrototypeLayout() {
334                    return _layoutSetPrototypeLayout;
335            }
336    
337            @Override
338            public String getLayoutSetPrototypeLayoutProperty(String key) {
339                    if (_layoutSetPrototypeLayout == null) {
340                            return StringPool.BLANK;
341                    }
342    
343                    UnicodeProperties typeSettingsProperties =
344                            _layoutSetPrototypeLayout.getTypeSettingsProperties();
345    
346                    return typeSettingsProperties.getProperty(key);
347            }
348    
349            @Override
350            public LayoutTemplate getLayoutTemplate() {
351                    String themeId = getThemeId();
352    
353                    LayoutTemplate layoutTemplate =
354                            LayoutTemplateLocalServiceUtil.getLayoutTemplate(
355                                    getLayoutTemplateId(), false, themeId);
356    
357                    if (layoutTemplate == null) {
358                            layoutTemplate = new LayoutTemplateImpl(
359                                    StringPool.BLANK, StringPool.BLANK);
360    
361                            List<String> columns = new ArrayList<>();
362    
363                            for (int i = 1; i <= 10; i++) {
364                                    columns.add(LayoutTypePortletConstants.COLUMN_PREFIX + i);
365                            }
366    
367                            layoutTemplate.setColumns(columns);
368                    }
369    
370                    return layoutTemplate;
371            }
372    
373            @Override
374            public String getLayoutTemplateId() {
375                    return GetterUtil.getString(
376                            getTypeSettingsProperty(
377                                    LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID));
378            }
379    
380            @Override
381            public String getModeAbout() {
382                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_ABOUT);
383            }
384    
385            @Override
386            public String getModeConfig() {
387                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_CONFIG);
388            }
389    
390            @Override
391            public String getModeEdit() {
392                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_EDIT);
393            }
394    
395            @Override
396            public String getModeEditDefaults() {
397                    return getTypeSettingsProperty(
398                            LayoutTypePortletConstants.MODE_EDIT_DEFAULTS);
399            }
400    
401            @Override
402            public String getModeEditGuest() {
403                    return getTypeSettingsProperty(
404                            LayoutTypePortletConstants.MODE_EDIT_GUEST);
405            }
406    
407            @Override
408            public String getModeHelp() {
409                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_HELP);
410            }
411    
412            @Override
413            public String getModePreview() {
414                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_PREVIEW);
415            }
416    
417            @Override
418            public String getModePrint() {
419                    return getTypeSettingsProperty(LayoutTypePortletConstants.MODE_PRINT);
420            }
421    
422            @Override
423            public int getNumOfColumns() {
424                    return getLayoutTemplate().getColumns().size();
425            }
426    
427            @Override
428            public PortalPreferences getPortalPreferences() {
429                    return _portalPreferences;
430            }
431    
432            @Override
433            public List<String> getPortletIds() {
434                    List<String> portletIds = new ArrayList<>();
435    
436                    List<String> columns = getColumns();
437    
438                    for (int i = 0; i < columns.size(); i++) {
439                            String columnId = columns.get(i);
440    
441                            String columnValue = getColumnValue(columnId);
442    
443                            portletIds.addAll(
444                                    ListUtil.fromArray(StringUtil.split(columnValue)));
445                    }
446    
447                    return portletIds;
448            }
449    
450            @Override
451            public List<Portlet> getPortlets() {
452                    List<String> portletIds = getPortletIds();
453    
454                    List<Portlet> portlets = new ArrayList<>(portletIds.size());
455    
456                    for (int i = 0; i < portletIds.size(); i++) {
457                            String portletId = portletIds.get(i);
458    
459                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
460                                    getCompanyId(), portletId);
461    
462                            if (portlet != null) {
463                                    portlets.add(portlet);
464                            }
465                    }
466    
467                    return portlets;
468            }
469    
470            @Override
471            public String getStateMax() {
472                    return getTypeSettingsProperty(LayoutTypePortletConstants.STATE_MAX);
473            }
474    
475            @Override
476            public String getStateMaxPortletId() {
477                    String[] stateMax = StringUtil.split(getStateMax());
478    
479                    if (stateMax.length > 0) {
480                            return stateMax[0];
481                    }
482                    else {
483                            return StringPool.BLANK;
484                    }
485            }
486    
487            @Override
488            public String getStateMin() {
489                    return getTypeSettingsProperty(LayoutTypePortletConstants.STATE_MIN);
490            }
491    
492            @Override
493            public boolean hasDefaultScopePortletId(long groupId, String portletId) {
494                    if (hasPortletId(portletId)) {
495                            long scopeGroupId = PortalUtil.getScopeGroupId(
496                                    getLayout(), portletId);
497    
498                            if (groupId == scopeGroupId) {
499                                    return true;
500                            }
501                    }
502    
503                    return false;
504            }
505    
506            @Override
507            public boolean hasModeAboutPortletId(String portletId) {
508                    return StringUtil.contains(getModeAbout(), portletId);
509            }
510    
511            @Override
512            public boolean hasModeConfigPortletId(String portletId) {
513                    return StringUtil.contains(getModeConfig(), portletId);
514            }
515    
516            @Override
517            public boolean hasModeEditDefaultsPortletId(String portletId) {
518                    return StringUtil.contains(getModeEditDefaults(), portletId);
519            }
520    
521            @Override
522            public boolean hasModeEditGuestPortletId(String portletId) {
523                    return StringUtil.contains(getModeEditGuest(), portletId);
524            }
525    
526            @Override
527            public boolean hasModeEditPortletId(String portletId) {
528                    return StringUtil.contains(getModeEdit(), portletId);
529            }
530    
531            @Override
532            public boolean hasModeHelpPortletId(String portletId) {
533                    return StringUtil.contains(getModeHelp(), portletId);
534            }
535    
536            @Override
537            public boolean hasModePreviewPortletId(String portletId) {
538                    return StringUtil.contains(getModePreview(), portletId);
539            }
540    
541            @Override
542            public boolean hasModePrintPortletId(String portletId) {
543                    return StringUtil.contains(getModePrint(), portletId);
544            }
545    
546            @Override
547            public boolean hasModeViewPortletId(String portletId) {
548                    if (hasModeAboutPortletId(portletId) ||
549                            hasModeConfigPortletId(portletId) ||
550                            hasModeEditPortletId(portletId) ||
551                            hasModeEditDefaultsPortletId(portletId) ||
552                            hasModeEditGuestPortletId(portletId) ||
553                            hasModeHelpPortletId(portletId) ||
554                            hasModePreviewPortletId(portletId) ||
555                            hasModePrintPortletId(portletId)) {
556    
557                            return false;
558                    }
559                    else {
560                            return true;
561                    }
562            }
563    
564            @Override
565            public boolean hasPortletId(String portletId) {
566                    return hasPortletId(portletId, false);
567            }
568    
569            @Override
570            public boolean hasPortletId(String portletId, boolean strict) {
571                    List<String> columns = getColumns();
572    
573                    for (String columnId : columns) {
574                            if (hasNonstaticPortletId(columnId, portletId)) {
575                                    return true;
576                            }
577    
578                            if (hasStaticPortletId(columnId, portletId)) {
579                                    return true;
580                            }
581                    }
582    
583                    Layout layout = getLayout();
584    
585                    if (layout.isTypeControlPanel()) {
586                            return false;
587                    }
588    
589                    if (isCustomizable() && isCustomizedView()) {
590                            LayoutTypePortletImpl defaultLayoutTypePortletImpl =
591                                    getDefaultLayoutTypePortletImpl();
592    
593                            if (defaultLayoutTypePortletImpl.hasNonstaticPortletId(portletId)) {
594                                    return false;
595                            }
596                    }
597    
598                    if (!strict &&
599                            ((PortletPreferencesLocalServiceUtil.getPortletPreferencesCount(
600                                    PortletKeys.PREFS_OWNER_TYPE_LAYOUT, layout.getPlid(),
601                                    portletId) > 0) ||
602                             (PortletPreferencesLocalServiceUtil.getPortletPreferencesCount(
603                                     PortletKeys.PREFS_OWNER_TYPE_USER, layout.getPlid(),
604                                     portletId) > 0))) {
605    
606                            return true;
607                    }
608    
609                    return false;
610            }
611    
612            @Override
613            public boolean hasStateMax() {
614                    String[] stateMax = StringUtil.split(getStateMax());
615    
616                    if (stateMax.length > 0) {
617                            return true;
618                    }
619                    else {
620                            return false;
621                    }
622            }
623    
624            @Override
625            public boolean hasStateMaxPortletId(String portletId) {
626                    if (StringUtil.contains(getStateMax(), portletId)) {
627                            return true;
628                    }
629                    else {
630                            return false;
631                    }
632            }
633    
634            @Override
635            public boolean hasStateMin() {
636                    String[] stateMin = StringUtil.split(getStateMin());
637    
638                    if (stateMin.length > 0) {
639                            return true;
640                    }
641                    else {
642                            return false;
643                    }
644            }
645    
646            @Override
647            public boolean hasStateMinPortletId(String portletId) {
648                    if (StringUtil.contains(getStateMin(), portletId)) {
649                            return true;
650                    }
651                    else {
652                            return false;
653                    }
654            }
655    
656            @Override
657            public boolean hasStateNormalPortletId(String portletId) {
658                    if (hasStateMaxPortletId(portletId) ||
659                            hasStateMinPortletId(portletId)) {
660    
661                            return false;
662                    }
663                    else {
664                            return true;
665                    }
666            }
667    
668            @Override
669            public boolean hasUpdatePermission() {
670                    return _updatePermission;
671            }
672    
673            @Override
674            public boolean isCacheable() {
675                    List<Portlet> portlets = new ArrayList<>();
676    
677                    for (String columnId : getColumns()) {
678                            List<Portlet> columnPortlets = getAllPortlets(columnId);
679    
680                            for (Portlet portlet : columnPortlets) {
681                                    Portlet rootPortlet = portlet.getRootPortlet();
682    
683                                    if (!rootPortlet.isLayoutCacheable()) {
684                                            return false;
685                                    }
686                            }
687    
688                            portlets.addAll(columnPortlets);
689                    }
690    
691                    List<Portlet> staticPortlets = getStaticPortlets(
692                            PropsKeys.LAYOUT_STATIC_PORTLETS_ALL);
693    
694                    for (Portlet portlet : staticPortlets) {
695                            Portlet rootPortlet = portlet.getRootPortlet();
696    
697                            if (!rootPortlet.isLayoutCacheable()) {
698                                    return false;
699                            }
700                    }
701    
702                    List<Portlet> embeddedPortlets = getEmbeddedPortlets();
703    
704                    for (Portlet portlet : embeddedPortlets) {
705                            Portlet rootPortlet = portlet.getRootPortlet();
706    
707                            if (!rootPortlet.isLayoutCacheable()) {
708                                    return false;
709                            }
710                    }
711    
712                    return true;
713            }
714    
715            @Override
716            public boolean isColumnCustomizable(String columnId) {
717                    if (!isLayoutSetPrototype()) {
718                            String customizableString = getTypeSettingsProperty(
719                                    CustomizedPages.namespaceColumnId(columnId));
720    
721                            boolean customizable = GetterUtil.getBoolean(customizableString);
722    
723                            if (!customizable && hasUserPreferences()) {
724                                    String columnValue = _portalPreferences.getValue(
725                                            CustomizedPages.namespacePlid(getPlid()), columnId,
726                                            StringPool.NULL);
727    
728                                    if (!Validator.equals(columnValue, StringPool.NULL)) {
729                                            setUserPreference(columnId, null);
730                                    }
731                            }
732    
733                            return customizable;
734                    }
735    
736                    return false;
737            }
738    
739            @Override
740            public boolean isColumnDisabled(String columnId) {
741                    if ((isCustomizedView() && !isColumnCustomizable(columnId)) ||
742                            (!isCustomizedView() && !hasUpdatePermission())) {
743    
744                            return true;
745                    }
746    
747                    return false;
748            }
749    
750            @Override
751            public boolean isCustomizable() {
752                    for (String columnId : getColumns()) {
753                            if (isColumnCustomizable(columnId)) {
754                                    return true;
755                            }
756                    }
757    
758                    return false;
759            }
760    
761            @Override
762            public boolean isCustomizedView() {
763                    return _customizedView;
764            }
765    
766            @Override
767            public boolean isDefaultUpdated() {
768                    if (!isCustomizedView() || !hasUserPreferences()) {
769                            return false;
770                    }
771    
772                    String preferencesModifiedDateString = _portalPreferences.getValue(
773                            CustomizedPages.namespacePlid(getPlid()), _MODIFIED_DATE,
774                            _NULL_DATE);
775    
776                    DateFormat dateFormat = DateFormatFactoryUtil.getSimpleDateFormat(
777                            PropsValues.INDEX_DATE_FORMAT_PATTERN);
778    
779                    try {
780                            Date preferencesModifiedDate = dateFormat.parse(
781                                    preferencesModifiedDateString);
782    
783                            Layout layout = getLayout();
784    
785                            String propertiesModifiedDateString =
786                                    layout.getTypeSettingsProperty(_MODIFIED_DATE, _NULL_DATE);
787    
788                            Date propertiesModifiedDate = dateFormat.parse(
789                                    propertiesModifiedDateString);
790    
791                            return propertiesModifiedDate.after(preferencesModifiedDate);
792                    }
793                    catch (Exception e) {
794                            _log.error(e, e);
795                    }
796    
797                    return false;
798            }
799    
800            @Override
801            public boolean isPortletCustomizable(String portletId) {
802                    return isColumnCustomizable(getColumn(portletId));
803            }
804    
805            @Override
806            public boolean isPortletEmbedded(String portletId) {
807                    Layout layout = getLayout();
808    
809                    return layout.isPortletEmbedded(portletId, layout.getGroupId());
810            }
811    
812            @Override
813            public void movePortletId(
814                    long userId, String portletId, String columnId, int columnPos) {
815    
816                    if (!hasPortletId(portletId)) {
817                            return;
818                    }
819    
820                    _enablePortletLayoutListener = false;
821    
822                    try {
823                            removePortletId(userId, portletId, false);
824                            addPortletId(userId, portletId, columnId, columnPos, false, true);
825                    }
826                    finally {
827                            _enablePortletLayoutListener = true;
828                    }
829    
830                    Layout layout = getLayout();
831    
832                    try {
833                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
834                                    layout.getCompanyId(), portletId);
835    
836                            if (portlet != null) {
837                                    PortletLayoutListener portletLayoutListener =
838                                            portlet.getPortletLayoutListenerInstance();
839    
840                                    if (portletLayoutListener != null) {
841                                            portletLayoutListener.onMoveInLayout(
842                                                    portletId, layout.getPlid());
843                                    }
844                            }
845                    }
846                    catch (Exception e) {
847                            _log.error("Unable to fire portlet layout listener event", e);
848                    }
849            }
850    
851            @Override
852            public void removeCustomization(UnicodeProperties typeSettingsProperties) {
853                    for (String columnId : getColumns()) {
854                            if (!isColumnCustomizable(columnId)) {
855                                    continue;
856                            }
857    
858                            if (GetterUtil.getBoolean(
859                                            getTypeSettingsProperty(
860                                                    CustomizedPages.namespaceColumnId(columnId)))) {
861    
862                                    typeSettingsProperties.remove(
863                                            CustomizedPages.namespaceColumnId(columnId));
864                            }
865                    }
866            }
867    
868            @Override
869            public void removeModeAboutPortletId(String portletId) {
870                    setModeAbout(StringUtil.removeFromList(getModeAbout(), portletId));
871            }
872    
873            @Override
874            public void removeModeConfigPortletId(String portletId) {
875                    setModeConfig(StringUtil.removeFromList(getModeConfig(), portletId));
876            }
877    
878            @Override
879            public void removeModeEditDefaultsPortletId(String portletId) {
880                    setModeEditDefaults(
881                            StringUtil.removeFromList(getModeEditDefaults(), portletId));
882            }
883    
884            @Override
885            public void removeModeEditGuestPortletId(String portletId) {
886                    setModeEditGuest(
887                            StringUtil.removeFromList(getModeEditGuest(), portletId));
888            }
889    
890            @Override
891            public void removeModeEditPortletId(String portletId) {
892                    setModeEdit(StringUtil.removeFromList(getModeEdit(), portletId));
893            }
894    
895            @Override
896            public void removeModeHelpPortletId(String portletId) {
897                    setModeHelp(StringUtil.removeFromList(getModeHelp(), portletId));
898            }
899    
900            @Override
901            public void removeModePreviewPortletId(String portletId) {
902                    setModePreview(StringUtil.removeFromList(getModePreview(), portletId));
903            }
904    
905            @Override
906            public void removeModePrintPortletId(String portletId) {
907                    setModePrint(StringUtil.removeFromList(getModePrint(), portletId));
908            }
909    
910            @Override
911            public void removeModesPortletId(String portletId) {
912                    removeModeAboutPortletId(portletId);
913                    removeModeConfigPortletId(portletId);
914                    removeModeEditPortletId(portletId);
915                    removeModeEditDefaultsPortletId(portletId);
916                    removeModeEditGuestPortletId(portletId);
917                    removeModeHelpPortletId(portletId);
918                    removeModePreviewPortletId(portletId);
919                    removeModePrintPortletId(portletId);
920            }
921    
922            @Override
923            public void removeNestedColumns(String portletNamespace) {
924                    UnicodeProperties typeSettingsProperties = getTypeSettingsProperties();
925    
926                    UnicodeProperties newTypeSettingsProperties = new UnicodeProperties();
927    
928                    for (Map.Entry<String, String> entry :
929                                    typeSettingsProperties.entrySet()) {
930    
931                            String key = entry.getKey();
932    
933                            if (!key.startsWith(portletNamespace)) {
934                                    newTypeSettingsProperties.setProperty(key, entry.getValue());
935                            }
936                    }
937    
938                    Layout layout = getLayout();
939    
940                    layout.setTypeSettingsProperties(newTypeSettingsProperties);
941    
942                    String nestedColumnIds = GetterUtil.getString(
943                            getTypeSettingsProperty(
944                                    LayoutTypePortletConstants.NESTED_COLUMN_IDS));
945    
946                    String[] nestedColumnIdsArray = ArrayUtil.removeByPrefix(
947                            StringUtil.split(nestedColumnIds), portletNamespace);
948    
949                    setTypeSettingsProperty(
950                            LayoutTypePortletConstants.NESTED_COLUMN_IDS,
951                            StringUtil.merge(nestedColumnIdsArray));
952            }
953    
954            @Override
955            public void removePortletId(long userId, String portletId) {
956                    removePortletId(userId, portletId, true);
957            }
958    
959            @Override
960            public void removePortletId(
961                    long userId, String portletId, boolean cleanUp) {
962    
963                    try {
964                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
965                                    getCompanyId(), portletId);
966    
967                            if (portlet == null) {
968                                    _log.error(
969                                            "Portlet " + portletId +
970                                                    " cannot be removed because it is not registered");
971    
972                                    return;
973                            }
974    
975                            PermissionChecker permissionChecker =
976                                    PermissionThreadLocal.getPermissionChecker();
977    
978                            if (!LayoutPermissionUtil.contains(
979                                            permissionChecker, getLayout(), ActionKeys.UPDATE) &&
980                                    !isCustomizable()) {
981    
982                                    return;
983                            }
984                    }
985                    catch (Exception e) {
986                            _log.error(e, e);
987    
988                            return;
989                    }
990    
991                    List<String> columns = getColumns();
992    
993                    for (int i = 0; i < columns.size(); i++) {
994                            String columnId = columns.get(i);
995    
996                            if (isCustomizable() && isColumnDisabled(columnId)) {
997                                    continue;
998                            }
999    
1000                            String columnValue = StringPool.BLANK;
1001    
1002                            if (hasUserPreferences()) {
1003                                    columnValue = getUserPreference(columnId);
1004                            }
1005                            else {
1006                                    columnValue = getTypeSettingsProperty(columnId);
1007                            }
1008    
1009                            columnValue = StringUtil.removeFromList(columnValue, portletId);
1010    
1011                            if (hasUserPreferences()) {
1012                                    setUserPreference(columnId, columnValue);
1013                            }
1014                            else {
1015                                    setTypeSettingsProperty(columnId, columnValue);
1016                            }
1017                    }
1018    
1019                    if (cleanUp) {
1020                            try {
1021                                    onRemoveFromLayout(new String[] {portletId});
1022                            }
1023                            catch (Exception e) {
1024                                    _log.error(e, e);
1025                            }
1026                    }
1027            }
1028    
1029            @Override
1030            public void removeStateMaxPortletId(String portletId) {
1031                    setStateMax(StringUtil.removeFromList(getStateMax(), portletId));
1032            }
1033    
1034            @Override
1035            public void removeStateMinPortletId(String portletId) {
1036                    setStateMin(StringUtil.removeFromList(getStateMin(), portletId));
1037            }
1038    
1039            @Override
1040            public void removeStatesPortletId(String portletId) {
1041                    removeStateMaxPortletId(portletId);
1042                    removeStateMinPortletId(portletId);
1043            }
1044    
1045            @Override
1046            public void reorganizePortlets(
1047                    List<String> newColumns, List<String> oldColumns) {
1048    
1049                    String lastNewColumnId = newColumns.get(newColumns.size() - 1);
1050                    String lastNewColumnValue = getTypeSettingsProperty(lastNewColumnId);
1051    
1052                    for (String oldColumnId : oldColumns) {
1053                            if (!newColumns.contains(oldColumnId)) {
1054                                    String oldColumnValue = getTypeSettingsProperties().remove(
1055                                            oldColumnId);
1056    
1057                                    String[] portletIds = StringUtil.split(oldColumnValue);
1058    
1059                                    for (String portletId : portletIds) {
1060                                            lastNewColumnValue = StringUtil.add(
1061                                                    lastNewColumnValue, portletId);
1062                                    }
1063                            }
1064                    }
1065    
1066                    setTypeSettingsProperty(lastNewColumnId, lastNewColumnValue);
1067            }
1068    
1069            @Override
1070            public void resetModes() {
1071                    setModeAbout(StringPool.BLANK);
1072                    setModeConfig(StringPool.BLANK);
1073                    setModeEdit(StringPool.BLANK);
1074                    setModeEditDefaults(StringPool.BLANK);
1075                    setModeEditGuest(StringPool.BLANK);
1076                    setModeHelp(StringPool.BLANK);
1077                    setModePreview(StringPool.BLANK);
1078                    setModePrint(StringPool.BLANK);
1079            }
1080    
1081            @Override
1082            public void resetStates() {
1083                    setStateMax(StringPool.BLANK);
1084                    setStateMin(StringPool.BLANK);
1085            }
1086    
1087            @Override
1088            public void resetUserPreferences() {
1089                    if (!hasUserPreferences()) {
1090                            return;
1091                    }
1092    
1093                    long plid = getPlid();
1094    
1095                    Set<String> customPortletIds = new HashSet<>();
1096    
1097                    for (String columnId : getColumns()) {
1098                            String value = _portalPreferences.getValue(
1099                                    CustomizedPages.namespacePlid(plid), columnId);
1100    
1101                            for (String customPortletId : StringUtil.split(value)) {
1102                                    customPortletIds.add(customPortletId);
1103                            }
1104                    }
1105    
1106                    try {
1107                            onRemoveFromLayout(
1108                                    customPortletIds.toArray(new String[customPortletIds.size()]));
1109                    }
1110                    catch (Exception e) {
1111                            _log.error(e, e);
1112                    }
1113    
1114                    _portalPreferences.resetValues(CustomizedPages.namespacePlid(plid));
1115    
1116                    _portalPreferences.setValue(
1117                            CustomizedPages.namespacePlid(plid), _MODIFIED_DATE,
1118                            _dateFormat.format(new Date()));
1119            }
1120    
1121            @Override
1122            public void setCustomizedView(boolean customizedView) {
1123                    _customizedView = customizedView;
1124            }
1125    
1126            @Override
1127            public void setLayoutTemplateId(long userId, String newLayoutTemplateId) {
1128                    setLayoutTemplateId(userId, newLayoutTemplateId, true);
1129            }
1130    
1131            @Override
1132            public void setLayoutTemplateId(
1133                    long userId, String newLayoutTemplateId, boolean checkPermission) {
1134    
1135                    if (checkPermission &&
1136                            !PluginSettingLocalServiceUtil.hasPermission(
1137                                    userId, newLayoutTemplateId, Plugin.TYPE_LAYOUT_TEMPLATE)) {
1138    
1139                            return;
1140                    }
1141    
1142                    LayoutTemplate oldLayoutTemplate = getLayoutTemplate();
1143    
1144                    String themeId = getThemeId();
1145    
1146                    LayoutTemplate newLayoutTemplate =
1147                            LayoutTemplateLocalServiceUtil.getLayoutTemplate(
1148                                    newLayoutTemplateId, false, themeId);
1149    
1150                    if (newLayoutTemplate == null) {
1151                            if (_log.isWarnEnabled()) {
1152                                    _log.warn(
1153                                            "Unable to find layout template " + newLayoutTemplateId);
1154                            }
1155    
1156                            return;
1157                    }
1158    
1159                    setTypeSettingsProperty(
1160                            LayoutTypePortletConstants.LAYOUT_TEMPLATE_ID, newLayoutTemplateId);
1161    
1162                    List<String> oldColumns = oldLayoutTemplate.getColumns();
1163                    List<String> newColumns = newLayoutTemplate.getColumns();
1164    
1165                    reorganizePortlets(newColumns, oldColumns);
1166            }
1167    
1168            @Override
1169            public void setModeAbout(String modeAbout) {
1170                    setTypeSettingsProperty(
1171                            LayoutTypePortletConstants.MODE_ABOUT, modeAbout);
1172            }
1173    
1174            @Override
1175            public void setModeConfig(String modeConfig) {
1176                    setTypeSettingsProperty(
1177                            LayoutTypePortletConstants.MODE_CONFIG, modeConfig);
1178            }
1179    
1180            @Override
1181            public void setModeEdit(String modeEdit) {
1182                    setTypeSettingsProperty(LayoutTypePortletConstants.MODE_EDIT, modeEdit);
1183            }
1184    
1185            @Override
1186            public void setModeEditDefaults(String modeEditDefaults) {
1187                    setTypeSettingsProperty(
1188                            LayoutTypePortletConstants.MODE_EDIT_DEFAULTS, modeEditDefaults);
1189            }
1190    
1191            @Override
1192            public void setModeEditGuest(String modeEditGuest) {
1193                    setTypeSettingsProperty(
1194                            LayoutTypePortletConstants.MODE_EDIT_GUEST, modeEditGuest);
1195            }
1196    
1197            @Override
1198            public void setModeHelp(String modeHelp) {
1199                    setTypeSettingsProperty(LayoutTypePortletConstants.MODE_HELP, modeHelp);
1200            }
1201    
1202            @Override
1203            public void setModePreview(String modePreview) {
1204                    setTypeSettingsProperty(
1205                            LayoutTypePortletConstants.MODE_PREVIEW, modePreview);
1206            }
1207    
1208            @Override
1209            public void setModePrint(String modePrint) {
1210                    setTypeSettingsProperty(
1211                            LayoutTypePortletConstants.MODE_PRINT, modePrint);
1212            }
1213    
1214            @Override
1215            public void setPortalPreferences(PortalPreferences portalPreferences) {
1216                    _portalPreferences = portalPreferences;
1217            }
1218    
1219            @Override
1220            public void setStateMax(String stateMax) {
1221                    setTypeSettingsProperty(LayoutTypePortletConstants.STATE_MAX, stateMax);
1222            }
1223    
1224            @Override
1225            public void setStateMin(String stateMin) {
1226                    setTypeSettingsProperty(LayoutTypePortletConstants.STATE_MIN, stateMin);
1227            }
1228    
1229            @Override
1230            public void setUpdatePermission(boolean updatePermission) {
1231                    _updatePermission = updatePermission;
1232            }
1233    
1234            protected void addNestedColumn(String columnId) {
1235                    String nestedColumnIds = getTypeSettingsProperty(
1236                            LayoutTypePortletConstants.NESTED_COLUMN_IDS, StringPool.BLANK);
1237    
1238                    if (!nestedColumnIds.contains(columnId)) {
1239                            nestedColumnIds = StringUtil.add(nestedColumnIds, columnId);
1240    
1241                            setTypeSettingsProperty(
1242                                    LayoutTypePortletConstants.NESTED_COLUMN_IDS, nestedColumnIds);
1243                    }
1244            }
1245    
1246            protected String addPortletId(
1247                    long userId, String portletId, String columnId, int columnPos,
1248                    boolean checkPermission, boolean strictHasPortlet) {
1249    
1250                    portletId = JS.getSafeName(portletId);
1251    
1252                    Layout layout = getLayout();
1253    
1254                    Portlet portlet = null;
1255    
1256                    try {
1257                            portlet = PortletLocalServiceUtil.getPortletById(
1258                                    layout.getCompanyId(), portletId);
1259    
1260                            if (portlet == null) {
1261                                    if (_log.isWarnEnabled()) {
1262                                            _log.warn(
1263                                                    "Portlet " + portletId +
1264                                                            " cannot be added because it is not registered");
1265                                    }
1266    
1267                                    return null;
1268                            }
1269    
1270                            PermissionChecker permissionChecker =
1271                                    PermissionThreadLocal.getPermissionChecker();
1272    
1273                            if (checkPermission &&
1274                                    !PortletPermissionUtil.contains(
1275                                            permissionChecker, layout, portlet,
1276                                            ActionKeys.ADD_TO_PAGE)) {
1277    
1278                                    return null;
1279                            }
1280                    }
1281                    catch (Exception e) {
1282                            _log.error(e, e);
1283                    }
1284    
1285                    if (portlet.isSystem()) {
1286                            return null;
1287                    }
1288    
1289                    if (portlet.isInstanceable() &&
1290                            !PortletConstants.hasInstanceId(portletId)) {
1291    
1292                            portletId = PortletConstants.assemblePortletId(
1293                                    portletId, PortletConstants.generateInstanceId());
1294                    }
1295    
1296                    if (hasPortletId(portletId, strictHasPortlet)) {
1297                            return null;
1298                    }
1299    
1300                    if (columnId == null) {
1301                            LayoutTemplate layoutTemplate = getLayoutTemplate();
1302    
1303                            List<String> columns = layoutTemplate.getColumns();
1304    
1305                            if (!columns.isEmpty()) {
1306                                    columnId = columns.get(0);
1307                            }
1308                    }
1309    
1310                    if (columnId == null) {
1311                            return null;
1312                    }
1313    
1314                    if (isCustomizable()) {
1315                            if (isColumnDisabled(columnId)) {
1316                                    return null;
1317                            }
1318    
1319                            if ((PortletConstants.hasInstanceId(portletId) ||
1320                                     portlet.isPreferencesUniquePerLayout()) &&
1321                                    hasUserPreferences()) {
1322    
1323                                    portletId = PortletConstants.assemblePortletId(
1324                                            portletId, userId);
1325                            }
1326                    }
1327    
1328                    String columnValue = StringPool.BLANK;
1329    
1330                    if (hasUserPreferences()) {
1331                            columnValue = getUserPreference(columnId);
1332                    }
1333                    else {
1334                            columnValue = getTypeSettingsProperty(columnId);
1335                    }
1336    
1337                    if ((columnValue == null) &&
1338                            columnId.startsWith(_NESTED_PORTLETS_NAMESPACE)) {
1339    
1340                            addNestedColumn(columnId);
1341                    }
1342    
1343                    if (columnPos >= 0) {
1344                            List<String> portletIds = ListUtil.fromArray(
1345                                    StringUtil.split(columnValue));
1346    
1347                            if (columnPos <= portletIds.size()) {
1348                                    portletIds.add(columnPos, portletId);
1349                            }
1350                            else {
1351                                    portletIds.add(portletId);
1352                            }
1353    
1354                            columnValue = StringUtil.merge(portletIds);
1355                    }
1356                    else {
1357                            columnValue = StringUtil.add(columnValue, portletId);
1358                    }
1359    
1360                    if (hasUserPreferences()) {
1361                            setUserPreference(columnId, columnValue);
1362                    }
1363                    else {
1364                            setTypeSettingsProperty(columnId, columnValue);
1365                    }
1366    
1367                    try {
1368                            if (_enablePortletLayoutListener &&
1369                                    !portlet.isUndeployedPortlet()) {
1370    
1371                                    PortletLayoutListener portletLayoutListener =
1372                                            portlet.getPortletLayoutListenerInstance();
1373    
1374                                    if (portletLayoutListener != null) {
1375                                            portletLayoutListener.onAddToLayout(
1376                                                    portletId, layout.getPlid());
1377                                    }
1378                            }
1379                    }
1380                    catch (Exception e) {
1381                            _log.error("Unable to fire portlet layout listener event", e);
1382                    }
1383    
1384                    return portletId;
1385            }
1386    
1387            protected void copyPreferences(
1388                    long userId, String sourcePortletId, String targetPortletId) {
1389    
1390                    Layout layout = getLayout();
1391    
1392                    try {
1393                            PortletPreferencesIds portletPreferencesIds =
1394                                    PortletPreferencesFactoryUtil.getPortletPreferencesIds(
1395                                            layout.getGroupId(), 0, layout, sourcePortletId, false);
1396    
1397                            javax.portlet.PortletPreferences sourcePortletPreferences =
1398                                    PortletPreferencesLocalServiceUtil.getStrictPreferences(
1399                                            portletPreferencesIds);
1400    
1401                            portletPreferencesIds =
1402                                    PortletPreferencesFactoryUtil.getPortletPreferencesIds(
1403                                            layout.getGroupId(), userId, layout, targetPortletId,
1404                                            false);
1405    
1406                            PortletPreferencesLocalServiceUtil.updatePreferences(
1407                                    portletPreferencesIds.getOwnerId(),
1408                                    portletPreferencesIds.getOwnerType(),
1409                                    portletPreferencesIds.getPlid(),
1410                                    portletPreferencesIds.getPortletId(), sourcePortletPreferences);
1411                    }
1412                    catch (Exception e) {
1413                    }
1414            }
1415    
1416            protected void copyResourcePermissions(
1417                    String sourcePortletId, String targetPortletId) {
1418    
1419                    Layout layout = getLayout();
1420    
1421                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
1422                            getCompanyId(), sourcePortletId);
1423    
1424                    String sourcePortletPrimaryKey = PortletPermissionUtil.getPrimaryKey(
1425                            layout.getPlid(), sourcePortletId);
1426    
1427                    List<ResourcePermission> resourcePermissions =
1428                            ResourcePermissionLocalServiceUtil.getResourcePermissions(
1429                                    portlet.getCompanyId(), portlet.getPortletName(),
1430                                    PortletKeys.PREFS_OWNER_TYPE_USER, sourcePortletPrimaryKey);
1431    
1432                    for (ResourcePermission resourcePermission : resourcePermissions) {
1433                            String targetPortletPrimaryKey =
1434                                    PortletPermissionUtil.getPrimaryKey(
1435                                            layout.getPlid(), targetPortletId);
1436    
1437                            resourcePermission.setResourcePermissionId(
1438                                    CounterLocalServiceUtil.increment());
1439                            resourcePermission.setPrimKey(targetPortletPrimaryKey);
1440    
1441                            ResourcePermissionLocalServiceUtil.addResourcePermission(
1442                                    resourcePermission);
1443                    }
1444            }
1445    
1446            protected String getColumn(String portletId) {
1447                    String portletIdColumnId = StringPool.BLANK;
1448    
1449                    List<String> columnIds = getColumns();
1450    
1451                    for (String columnId : columnIds) {
1452                            String columnValue = getColumnValue(columnId);
1453    
1454                            String[] portletIds = StringUtil.split(columnValue);
1455    
1456                            for (String columnPortletId : portletIds) {
1457                                    if (columnPortletId.equals(portletId)) {
1458                                            return columnId;
1459                                    }
1460    
1461                                    if (Validator.isNull(portletIdColumnId) &&
1462                                            PortletConstants.hasIdenticalRootPortletId(
1463                                                    columnPortletId, portletId)) {
1464    
1465                                            portletIdColumnId = columnId;
1466                                    }
1467                            }
1468                    }
1469    
1470                    return portletIdColumnId;
1471            }
1472    
1473            protected List<String> getColumns() {
1474                    List<String> columns = new ArrayList<>();
1475    
1476                    Layout layout = getLayout();
1477    
1478                    if (layout.isTypePortlet()) {
1479                            LayoutTemplate layoutTemplate = getLayoutTemplate();
1480    
1481                            columns.addAll(layoutTemplate.getColumns());
1482    
1483                            columns.addAll(getNestedColumns());
1484                    }
1485                    else if (layout.isTypePanel()) {
1486                            columns.add("panelSelectedPortlets");
1487                    }
1488    
1489                    return columns;
1490            }
1491    
1492            protected String getColumnValue(String columnId) {
1493                    if (hasUserPreferences() && isCustomizable() &&
1494                            !isColumnDisabled(columnId)) {
1495    
1496                            return getUserPreference(columnId);
1497                    }
1498    
1499                    return getTypeSettingsProperty(columnId);
1500            }
1501    
1502            protected long getCompanyId() {
1503                    Layout layout = getLayout();
1504    
1505                    return layout.getCompanyId();
1506            }
1507    
1508            protected LayoutTypePortletImpl getDefaultLayoutTypePortletImpl() {
1509                    if (!isCustomizedView()) {
1510                            return this;
1511                    }
1512    
1513                    LayoutTypePortletImpl defaultLayoutTypePortletImpl =
1514                            (LayoutTypePortletImpl)LayoutTypePortletFactoryUtil.create(
1515                                    getLayout());
1516    
1517                    defaultLayoutTypePortletImpl._layoutSetPrototypeLayout =
1518                            _layoutSetPrototypeLayout;
1519                    defaultLayoutTypePortletImpl._updatePermission = _updatePermission;
1520    
1521                    return defaultLayoutTypePortletImpl;
1522            }
1523    
1524            protected List<String> getNestedColumns() {
1525                    String nestedColumnIds = getTypeSettingsProperty(
1526                            LayoutTypePortletConstants.NESTED_COLUMN_IDS);
1527    
1528                    return ListUtil.fromArray(StringUtil.split(nestedColumnIds));
1529            }
1530    
1531            protected long getPlid() {
1532                    Layout layout = getLayout();
1533    
1534                    return layout.getPlid();
1535            }
1536    
1537            protected String[] getStaticPortletIds(String position) {
1538                    Layout layout = getLayout();
1539    
1540                    String selector1 = StringPool.BLANK;
1541    
1542                    Group group = null;
1543    
1544                    try {
1545                            group = layout.getGroup();
1546                    }
1547                    catch (PortalException pe) {
1548                            _log.error("Unable to get group " + layout.getGroupId());
1549    
1550                            return new String[0];
1551                    }
1552    
1553                    if (group.isUser()) {
1554                            selector1 = LayoutTypePortletConstants.STATIC_PORTLET_USER_SELECTOR;
1555                    }
1556                    else if (group.isOrganization()) {
1557                            selector1 =
1558                                    LayoutTypePortletConstants.STATIC_PORTLET_ORGANIZATION_SELECTOR;
1559                    }
1560                    else if (group.isRegularSite()) {
1561                            selector1 =
1562                                    LayoutTypePortletConstants.STATIC_PORTLET_REGULAR_SITE_SELECTOR;
1563                    }
1564    
1565                    String selector2 = layout.getFriendlyURL();
1566    
1567                    String[] portletIds = PropsUtil.getArray(
1568                            position, new Filter(selector1, selector2));
1569    
1570                    for (int i = 0; i < portletIds.length; i++) {
1571                            portletIds[i] = JS.getSafeName(portletIds[i]);
1572                    }
1573    
1574                    return portletIds;
1575            }
1576    
1577            protected List<Portlet> getStaticPortlets(String position) {
1578                    String[] portletIds = getStaticPortletIds(position);
1579    
1580                    List<Portlet> portlets = new ArrayList<>();
1581    
1582                    for (String portletId : portletIds) {
1583                            if (Validator.isNull(portletId) ||
1584                                    hasNonstaticPortletId(portletId)) {
1585    
1586                                    continue;
1587                            }
1588    
1589                            Portlet portlet = PortletLocalServiceUtil.getPortletById(
1590                                    getCompanyId(), portletId);
1591    
1592                            if (portlet != null) {
1593                                    Portlet staticPortlet = portlet;
1594    
1595                                    if (portlet.isInstanceable()) {
1596    
1597                                            // Instanceable portlets do not need to be cloned because
1598                                            // they are already cloned. See the method getPortletById in
1599                                            // the class PortletLocalServiceImpl and how it references
1600                                            // the method getClonedInstance in the class PortletImpl.
1601    
1602                                    }
1603                                    else {
1604                                            staticPortlet = (Portlet)staticPortlet.clone();
1605                                    }
1606    
1607                                    staticPortlet.setStatic(true);
1608    
1609                                    if (position.startsWith("layout.static.portlets.start")) {
1610                                            staticPortlet.setStaticStart(true);
1611                                    }
1612    
1613                                    portlets.add(staticPortlet);
1614                            }
1615                    }
1616    
1617                    return portlets;
1618            }
1619    
1620            protected String getThemeId() {
1621                    String themeId = null;
1622    
1623                    try {
1624                            Layout layout = getLayout();
1625    
1626                            Theme theme = layout.getTheme();
1627    
1628                            if (theme != null) {
1629                                    themeId = theme.getThemeId();
1630                            }
1631                            else {
1632                                    themeId = layout.getThemeId();
1633                            }
1634                    }
1635                    catch (Exception e) {
1636                            _log.error(e, e);
1637                    }
1638    
1639                    return themeId;
1640            }
1641    
1642            protected String getUserPreference(String key) {
1643                    String value = StringPool.BLANK;
1644    
1645                    if (!hasUserPreferences()) {
1646                            return value;
1647                    }
1648    
1649                    value = _portalPreferences.getValue(
1650                            CustomizedPages.namespacePlid(getPlid()), key, StringPool.NULL);
1651    
1652                    if (!value.equals(StringPool.NULL)) {
1653                            return value;
1654                    }
1655    
1656                    value = getTypeSettingsProperty(key);
1657    
1658                    if (Validator.isNull(value)) {
1659                            return value;
1660                    }
1661    
1662                    List<String> newPortletIds = new ArrayList<>();
1663    
1664                    PermissionChecker permissionChecker =
1665                            PermissionThreadLocal.getPermissionChecker();
1666    
1667                    String[] portletIds = StringUtil.split(value);
1668    
1669                    for (String portletId : portletIds) {
1670                            try {
1671                                    if (!PortletPermissionUtil.contains(
1672                                                    permissionChecker, getLayout(), portletId,
1673                                                    ActionKeys.VIEW, true)) {
1674    
1675                                            continue;
1676                                    }
1677    
1678                                    String rootPortletId = PortletConstants.getRootPortletId(
1679                                            portletId);
1680    
1681                                    if (!PortletPermissionUtil.contains(
1682                                                    permissionChecker, rootPortletId,
1683                                                    ActionKeys.ADD_TO_PAGE)) {
1684    
1685                                            continue;
1686                                    }
1687                            }
1688                            catch (Exception e) {
1689                                    _log.error(e, e);
1690                            }
1691    
1692                            String newPortletId = null;
1693    
1694                            boolean preferencesUniquePerLayout = false;
1695    
1696                            try {
1697                                    Portlet portlet = PortletLocalServiceUtil.getPortletById(
1698                                            getCompanyId(), portletId);
1699    
1700                                    preferencesUniquePerLayout =
1701                                            portlet.isPreferencesUniquePerLayout();
1702                            }
1703                            catch (SystemException se) {
1704                                    _log.error(se, se);
1705                            }
1706    
1707                            if (PortletConstants.hasInstanceId(portletId) ||
1708                                    preferencesUniquePerLayout) {
1709    
1710                                    String instanceId = null;
1711    
1712                                    if (PortletConstants.hasInstanceId(portletId)) {
1713                                            instanceId = PortletConstants.generateInstanceId();
1714                                    }
1715    
1716                                    newPortletId = PortletConstants.assemblePortletId(
1717                                            portletId, _portalPreferences.getUserId(), instanceId);
1718    
1719                                    copyPreferences(
1720                                            _portalPreferences.getUserId(), portletId, newPortletId);
1721    
1722                                    copyResourcePermissions(portletId, newPortletId);
1723                            }
1724                            else {
1725                                    newPortletId = portletId;
1726                            }
1727    
1728                            newPortletIds.add(newPortletId);
1729                    }
1730    
1731                    value = StringUtil.merge(newPortletIds);
1732    
1733                    setUserPreference(key, value);
1734    
1735                    return value;
1736            }
1737    
1738            protected boolean hasNonstaticPortletId(String portletId) {
1739                    LayoutTemplate layoutTemplate = getLayoutTemplate();
1740    
1741                    List<String> columns = layoutTemplate.getColumns();
1742    
1743                    for (int i = 0; i < columns.size(); i++) {
1744                            String columnId = columns.get(i);
1745    
1746                            if (hasNonstaticPortletId(columnId, portletId)) {
1747                                    return true;
1748                            }
1749                    }
1750    
1751                    return false;
1752            }
1753    
1754            protected boolean hasNonstaticPortletId(String columnId, String portletId) {
1755                    String columnValue = getColumnValue(columnId);
1756    
1757                    String[] columnValues = StringUtil.split(columnValue);
1758    
1759                    for (String nonstaticPortletId : columnValues) {
1760                            if (nonstaticPortletId.equals(portletId) ||
1761                                    PortletConstants.getRootPortletId(
1762                                            nonstaticPortletId).equals(portletId)) {
1763    
1764                                    return true;
1765                            }
1766                    }
1767    
1768                    return false;
1769            }
1770    
1771            protected boolean hasStaticPortletId(String columnId, String portletId) {
1772                    String[] staticPortletIdsStart = getStaticPortletIds(
1773                            PropsKeys.LAYOUT_STATIC_PORTLETS_START + columnId);
1774    
1775                    String[] staticPortletIdsEnd = getStaticPortletIds(
1776                            PropsKeys.LAYOUT_STATIC_PORTLETS_END + columnId);
1777    
1778                    for (String staticPortletId : staticPortletIdsStart) {
1779                            if (staticPortletId.equals(portletId) ||
1780                                    PortletConstants.getRootPortletId(
1781                                            staticPortletId).equals(portletId)) {
1782    
1783                                    return true;
1784                            }
1785                    }
1786    
1787                    for (String staticPortletId : staticPortletIdsEnd) {
1788                            if (staticPortletId.equals(portletId) ||
1789                                    PortletConstants.getRootPortletId(
1790                                            staticPortletId).equals(portletId)) {
1791    
1792                                    return true;
1793                            }
1794                    }
1795    
1796                    return false;
1797            }
1798    
1799            protected boolean hasUserPreferences() {
1800                    if (_portalPreferences != null) {
1801                            return true;
1802                    }
1803    
1804                    return false;
1805            }
1806    
1807            protected boolean isLayoutSetPrototype() {
1808                    try {
1809                            Layout layout = getLayout();
1810    
1811                            LayoutSet layoutSet = layout.getLayoutSet();
1812    
1813                            Group group = layoutSet.getGroup();
1814    
1815                            return group.isLayoutSetPrototype();
1816                    }
1817                    catch (Exception e) {
1818                            _log.error(e, e);
1819                    }
1820    
1821                    return false;
1822            }
1823    
1824            protected void onRemoveFromLayout(String[] portletIds) {
1825                    Set<String> portletIdList = new HashSet<>();
1826    
1827                    for (String portletId : portletIds) {
1828                            removeModesPortletId(portletId);
1829                            removeStatesPortletId(portletId);
1830    
1831                            portletIdList.add(portletId);
1832    
1833                            String rootPortletId = PortletConstants.getRootPortletId(portletId);
1834    
1835                            if (rootPortletId.equals(PortletKeys.NESTED_PORTLETS)) {
1836                                    String portletNamespace = PortalUtil.getPortletNamespace(
1837                                            portletId);
1838    
1839                                    UnicodeProperties typeSettingsProperties =
1840                                            getTypeSettingsProperties();
1841    
1842                                    for (Map.Entry<String, String> entry :
1843                                                    typeSettingsProperties.entrySet()) {
1844    
1845                                            String key = entry.getKey();
1846    
1847                                            if (!key.startsWith(portletNamespace)) {
1848                                                    continue;
1849                                            }
1850    
1851                                            String nestedPortletIds = entry.getValue();
1852    
1853                                            for (String nestedPortletId :
1854                                                            StringUtil.split(nestedPortletIds)) {
1855    
1856                                                    removeModesPortletId(nestedPortletId);
1857                                                    removeStatesPortletId(nestedPortletId);
1858    
1859                                                    portletIdList.add(nestedPortletId);
1860                                            }
1861                                    }
1862    
1863                                    removeNestedColumns(portletNamespace);
1864                            }
1865    
1866                            Portlet portlet = PortletLocalServiceUtil.getPortletById(portletId);
1867    
1868                            if (portlet == null) {
1869                                    continue;
1870                            }
1871    
1872                            PortletLayoutListener portletLayoutListener =
1873                                    portlet.getPortletLayoutListenerInstance();
1874    
1875                            if (portletLayoutListener == null) {
1876                                    continue;
1877                            }
1878    
1879                            portletLayoutListener.updatePropertiesOnRemoveFromLayout(
1880                                    portletId, getTypeSettingsProperties());
1881                    }
1882    
1883                    try {
1884                            PortletLocalServiceUtil.deletePortlets(
1885                                    getCompanyId(),
1886                                    portletIdList.toArray(new String[portletIdList.size()]),
1887                                    getPlid());
1888                    }
1889                    catch (PortalException pe) {
1890                            _log.error(pe, pe);
1891                    }
1892            }
1893    
1894            protected void setUserPreference(String key, String value) {
1895                    if (!hasUserPreferences()) {
1896                            return;
1897                    }
1898    
1899                    _portalPreferences.setValue(
1900                            CustomizedPages.namespacePlid(getPlid()), key, value);
1901    
1902                    _portalPreferences.setValue(
1903                            CustomizedPages.namespacePlid(getPlid()), _MODIFIED_DATE,
1904                            _dateFormat.format(new Date()));
1905            }
1906    
1907            private static final String _MODIFIED_DATE = "modifiedDate";
1908    
1909            private static final String _NESTED_PORTLETS_NAMESPACE =
1910                    PortalUtil.getPortletNamespace(PortletKeys.NESTED_PORTLETS);
1911    
1912            private static final String _NULL_DATE = "00000000000000";
1913    
1914            private static final Log _log = LogFactoryUtil.getLog(
1915                    LayoutTypePortletImpl.class);
1916    
1917            private boolean _customizedView;
1918            private final Format _dateFormat =
1919                    FastDateFormatFactoryUtil.getSimpleDateFormat(
1920                            PropsValues.INDEX_DATE_FORMAT_PATTERN);
1921            private boolean _enablePortletLayoutListener = true;
1922            private Layout _layoutSetPrototypeLayout;
1923            private PortalPreferences _portalPreferences;
1924            private boolean _updatePermission;
1925    
1926    }