001/*
002 *  Copyright 2010 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.web.clientsideelement;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.avalon.framework.service.ServiceManager;
025
026import org.ametys.core.observation.Event;
027import org.ametys.core.observation.ObservationManager;
028import org.ametys.core.ui.Callable;
029import org.ametys.core.ui.ClientSideElement;
030import org.ametys.plugins.repository.AmetysObject;
031import org.ametys.plugins.repository.ModifiableAmetysObject;
032import org.ametys.plugins.repository.data.ametysobject.ModelLessDataAwareAmetysObject;
033import org.ametys.plugins.repository.data.ametysobject.ModifiableModelLessDataAwareAmetysObject;
034import org.ametys.runtime.i18n.I18nizableTextParameter;
035import org.ametys.runtime.i18n.I18nizableText;
036import org.ametys.web.ObservationConstants;
037import org.ametys.web.repository.page.ModifiablePage;
038import org.ametys.web.repository.page.Page;
039import org.ametys.web.repository.page.PagesContainer;
040import org.ametys.web.repository.page.jcr.DefaultPage;
041import org.ametys.web.repository.sitemap.Sitemap;
042
043/**
044 * This {@link ClientSideElement} creates a button representing the SEO properties of a page
045 */
046public class PageRobotsClientSideElement extends AbstractPagesContainerClientSideElement
047{
048    private ObservationManager _observationManager;
049    
050    @Override
051    public void service(ServiceManager smanager) throws ServiceException
052    {
053        super.service(smanager);
054        _observationManager = (ObservationManager) smanager.lookup(ObservationManager.ROLE);
055    }
056    
057    /**
058     * Allow/Disallow the robots on a page or sitemap
059     * @param pageIds the selected pages or sitemap
060     * @param exclude true to disallow the robots on the selected pages, false otherwise 
061     * @return true if succeeds
062     */
063    @Callable
064    public boolean editRobots (List<String> pageIds, boolean exclude)
065    {
066        for (String id : pageIds)
067        {
068            ModifiableModelLessDataAwareAmetysObject ao = _resolver.resolveById(id);
069            ao.setValue(DefaultPage.METADATA_ROBOTS_DISALLOW, exclude);
070            ((ModifiableAmetysObject) ao).saveChanges();
071            
072            Map<String, Object> eventParams = new HashMap<>();
073            eventParams.put(ao instanceof Sitemap ? ObservationConstants.ARGS_SITEMAP : ObservationConstants.ARGS_PAGE, ao);
074            _observationManager.notify(new Event(ObservationConstants.EVENT_ROBOTS_CHANGED, _currentUserProvider.getUser(), eventParams));
075        } 
076        
077        return true;
078    }
079    
080    /**
081     * Get the robots status of given pages or sitemap
082     * @param pageIds The page ids or sitemap id
083     * @return the result
084     */
085    @Callable
086    public Map<String, Object> getStatus (List<String> pageIds)
087    {
088        Map<String, Object> results = new HashMap<>();
089        
090        results.put("nomodifiable-pages", new ArrayList<Map<String, Object>>());
091        results.put("noright-pages", new ArrayList<Map<String, Object>>());
092        results.put("included-pages", new ArrayList<Map<String, Object>>());
093        results.put("excluded-pages", new ArrayList<Map<String, Object>>());
094        results.put("parent-excluded-pages", new ArrayList<Map<String, Object>>());
095    
096        for (String pageId : pageIds)
097        {
098            PagesContainer pageOrSitemap = _resolver.resolveById(pageId);
099            
100            Map<String, Object> pageParams = getPagesContainerDefaultParameters(pageOrSitemap);
101            
102            if (pageOrSitemap instanceof Page && !(pageOrSitemap instanceof ModifiablePage))
103            {
104                pageParams.put("description", getNoModifiablePageDescription((Page) pageOrSitemap));
105
106                @SuppressWarnings("unchecked")
107                List<Map<String, Object>> nomodifiablePages = (List<Map<String, Object>>) results.get("nomodifiable-pages");
108                nomodifiablePages.add(pageParams);
109            }
110            else if (!hasRight(pageOrSitemap))
111            {
112                pageParams.put("description", getNoRightPagesContainerDescription(pageOrSitemap));
113
114                @SuppressWarnings("unchecked")
115                List<Map<String, Object>> norightPages = (List<Map<String, Object>>) results.get("noright-pages");
116                norightPages.add(pageParams);
117            }
118            else
119            {
120                if (_isExcludedFromSEO((ModelLessDataAwareAmetysObject) pageOrSitemap))
121                {
122                    pageParams.put("description", _getExcludedDescription(pageOrSitemap));
123                    
124                    @SuppressWarnings("unchecked")
125                    List<Map<String, Object>> excludedPages = (List<Map<String, Object>>) results.get("excluded-pages");
126                    excludedPages.add(pageParams);
127                }
128                else if (_isParentExcludedFromSEO(pageOrSitemap))
129                {
130                    pageParams.put("description", _getParentExcludedDescription(pageOrSitemap));
131                    
132                    @SuppressWarnings("unchecked")
133                    List<Map<String, Object>> excludedPages = (List<Map<String, Object>>) results.get("parent-excluded-pages");
134                    excludedPages.add(pageParams);
135                }
136                else
137                {
138                    pageParams.put("description", _getIncludedDescription(pageOrSitemap));
139                    
140                    @SuppressWarnings("unchecked")
141                    List<Map<String, Object>> includedPages = (List<Map<String, Object>>) results.get("included-pages");
142                    includedPages.add(pageParams);
143                    
144                }
145            }
146        }
147        
148        return results;
149    }
150    
151    private I18nizableText _getExcludedDescription (PagesContainer pageOrSitemap)
152    {
153        if (pageOrSitemap instanceof Page)
154        {
155            List<String> i18nParameters = new ArrayList<>();
156            i18nParameters.add(((Page) pageOrSitemap).getTitle());
157            
158            I18nizableText ed = (I18nizableText) this._script.getParameters().get("page-excluded-description");
159            return new I18nizableText(ed.getCatalogue(), ed.getKey(), i18nParameters);
160        }
161        else
162        {
163            Map<String, I18nizableTextParameter> i18nParameters = new HashMap<>();
164            i18nParameters.put("title", getSitemapTitle((Sitemap) pageOrSitemap));
165            i18nParameters.put("name", new I18nizableText(pageOrSitemap.getSitemapName()));
166            
167            I18nizableText ed = (I18nizableText) this._script.getParameters().get("sitemap-excluded-description");
168            return new I18nizableText(ed.getCatalogue(), ed.getKey(), i18nParameters);
169        }
170    }
171    
172    private I18nizableText _getParentExcludedDescription (PagesContainer pageOrSitemap)
173    {
174        return _getExcludedDescription(pageOrSitemap);
175    }
176    
177    private I18nizableText _getIncludedDescription (PagesContainer pageOrSitemap)
178    {
179        if (pageOrSitemap instanceof Page)
180        {
181            List<String> i18nParameters = new ArrayList<>();
182            i18nParameters.add(((Page) pageOrSitemap).getTitle());
183            
184            I18nizableText ed = (I18nizableText) this._script.getParameters().get("page-included-description");
185            return new I18nizableText(ed.getCatalogue(), ed.getKey(), i18nParameters);
186        }
187        else
188        {
189            Map<String, I18nizableTextParameter> i18nParameters = new HashMap<>();
190            i18nParameters.put("title", getSitemapTitle((Sitemap) pageOrSitemap));
191            i18nParameters.put("name", new I18nizableText(pageOrSitemap.getSitemapName()));
192            
193            I18nizableText ed = (I18nizableText) this._script.getParameters().get("sitemap-included-description");
194            return new I18nizableText(ed.getCatalogue(), ed.getKey(), i18nParameters);
195        }
196    }
197
198    private boolean _isExcludedFromSEO (ModelLessDataAwareAmetysObject pageOrSitemap)
199    {
200        return pageOrSitemap.getValue(DefaultPage.METADATA_ROBOTS_DISALLOW, false);
201    }
202    
203    private boolean _isParentExcludedFromSEO (PagesContainer pageOrSitemap)
204    {
205        AmetysObject parent = pageOrSitemap.getParent();
206        while (parent != null && parent instanceof PagesContainer)
207        {
208            boolean excluded = _isExcludedFromSEO((ModelLessDataAwareAmetysObject) parent);
209            if (excluded)
210            {
211                return true;
212            }
213            
214            parent = parent.getParent();
215        }
216        
217        return false;
218    }
219}