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.data.ametysobject.ModelLessDataAwareAmetysObject;
032import org.ametys.runtime.i18n.I18nizableText;
033import org.ametys.runtime.i18n.I18nizableTextParameter;
034import org.ametys.web.ObservationConstants;
035import org.ametys.web.repository.page.ModifiablePage;
036import org.ametys.web.repository.page.Page;
037import org.ametys.web.repository.page.SitemapElement;
038import org.ametys.web.repository.page.jcr.AbstractSitemapElement;
039import org.ametys.web.repository.page.jcr.DefaultPage;
040import org.ametys.web.repository.sitemap.Sitemap;
041
042/**
043 * This {@link ClientSideElement} creates a button representing the SEO properties of a page
044 */
045public class PageRobotsClientSideElement extends AbstractSitemapElementClientSideElement
046{
047    private ObservationManager _observationManager;
048    
049    @Override
050    public void service(ServiceManager smanager) throws ServiceException
051    {
052        super.service(smanager);
053        _observationManager = (ObservationManager) smanager.lookup(ObservationManager.ROLE);
054    }
055    
056    /**
057     * Allow/Disallow the robots on a page or sitemap
058     * @param pageIds the selected pages or sitemap
059     * @param exclude true to disallow the robots on the selected pages, false otherwise 
060     * @return the results with successful pages and pages with failure
061     */
062    @Callable (rights = Callable.SKIP_BUILTIN_CHECK)
063    public Map<String, Object> editRobots (List<String> pageIds, boolean exclude)
064    {
065        List<String> allRightIds = new ArrayList<>();
066        List<Map<String, Object>> noRightPages = new ArrayList<>();
067        
068        for (String id : pageIds)
069        {
070            AbstractSitemapElement sitemapElmt = _resolver.resolveById(id);
071            
072            if (!hasRight(sitemapElmt))
073            {
074                noRightPages.add(Map.of("id", id, "title", sitemapElmt.getTitle()));
075            }
076            else
077            {
078                sitemapElmt.setValue(DefaultPage.METADATA_ROBOTS_DISALLOW, exclude);
079                sitemapElmt.saveChanges();
080                allRightIds.add(id);
081                
082                Map<String, Object> eventParams = new HashMap<>();
083                eventParams.put(sitemapElmt instanceof Sitemap ? ObservationConstants.ARGS_SITEMAP : ObservationConstants.ARGS_SITEMAP_ELEMENT, sitemapElmt);
084                _observationManager.notify(new Event(ObservationConstants.EVENT_ROBOTS_CHANGED, _currentUserProvider.getUser(), eventParams));
085            }
086        } 
087        
088        return Map.of("allright-pages", allRightIds, "noright-pages", noRightPages);
089    }
090    
091    /**
092     * Get the robots status of given pages or sitemap
093     * @param pageIds The page ids or sitemap id
094     * @return the result
095     */
096    @Callable (rights = Callable.SKIP_BUILTIN_CHECK)
097    public Map<String, Object> getStatus (List<String> pageIds)
098    {
099        Map<String, Object> results = new HashMap<>();
100        
101        results.put("nomodifiable-pages", new ArrayList<>());
102        results.put("noright-pages", new ArrayList<>());
103        results.put("included-pages", new ArrayList<>());
104        results.put("excluded-pages", new ArrayList<>());
105        results.put("parent-excluded-pages", new ArrayList<>());
106    
107        for (String pageId : pageIds)
108        {
109            SitemapElement pageOrSitemap = _resolver.resolveById(pageId);
110            
111            Map<String, Object> pageParams = getSitemapElementDefaultParameters(pageOrSitemap);
112            
113            if (pageOrSitemap instanceof Page && !(pageOrSitemap instanceof ModifiablePage))
114            {
115                pageParams.put("description", getNoModifiablePageDescription((Page) pageOrSitemap));
116
117                @SuppressWarnings("unchecked")
118                List<Map<String, Object>> nomodifiablePages = (List<Map<String, Object>>) results.get("nomodifiable-pages");
119                nomodifiablePages.add(pageParams);
120            }
121            else if (!hasRight(pageOrSitemap))
122            {
123                pageParams.put("description", getNoRightSitemapElementDescription(pageOrSitemap));
124
125                @SuppressWarnings("unchecked")
126                List<Map<String, Object>> norightPages = (List<Map<String, Object>>) results.get("noright-pages");
127                norightPages.add(pageParams);
128            }
129            else
130            {
131                if (_isExcludedFromSEO((ModelLessDataAwareAmetysObject) pageOrSitemap))
132                {
133                    pageParams.put("description", _getExcludedDescription(pageOrSitemap));
134                    
135                    @SuppressWarnings("unchecked")
136                    List<Map<String, Object>> excludedPages = (List<Map<String, Object>>) results.get("excluded-pages");
137                    excludedPages.add(pageParams);
138                }
139                else if (_isParentExcludedFromSEO(pageOrSitemap))
140                {
141                    pageParams.put("description", _getParentExcludedDescription(pageOrSitemap));
142                    
143                    @SuppressWarnings("unchecked")
144                    List<Map<String, Object>> excludedPages = (List<Map<String, Object>>) results.get("parent-excluded-pages");
145                    excludedPages.add(pageParams);
146                }
147                else
148                {
149                    pageParams.put("description", _getIncludedDescription(pageOrSitemap));
150                    
151                    @SuppressWarnings("unchecked")
152                    List<Map<String, Object>> includedPages = (List<Map<String, Object>>) results.get("included-pages");
153                    includedPages.add(pageParams);
154                    
155                }
156            }
157        }
158        
159        return results;
160    }
161    
162    private I18nizableText _getExcludedDescription (SitemapElement pageOrSitemap)
163    {
164        if (pageOrSitemap instanceof Page)
165        {
166            List<String> i18nParameters = new ArrayList<>();
167            i18nParameters.add(((Page) pageOrSitemap).getTitle());
168            
169            I18nizableText ed = (I18nizableText) this._script.getParameters().get("page-excluded-description");
170            return new I18nizableText(ed.getCatalogue(), ed.getKey(), i18nParameters);
171        }
172        else
173        {
174            Map<String, I18nizableTextParameter> i18nParameters = new HashMap<>();
175            i18nParameters.put("title", getSitemapTitle((Sitemap) pageOrSitemap));
176            i18nParameters.put("name", new I18nizableText(pageOrSitemap.getSitemapName()));
177            
178            I18nizableText ed = (I18nizableText) this._script.getParameters().get("sitemap-excluded-description");
179            return new I18nizableText(ed.getCatalogue(), ed.getKey(), i18nParameters);
180        }
181    }
182    
183    private I18nizableText _getParentExcludedDescription (SitemapElement pageOrSitemap)
184    {
185        return _getExcludedDescription(pageOrSitemap);
186    }
187    
188    private I18nizableText _getIncludedDescription (SitemapElement pageOrSitemap)
189    {
190        if (pageOrSitemap instanceof Page)
191        {
192            List<String> i18nParameters = new ArrayList<>();
193            i18nParameters.add(((Page) pageOrSitemap).getTitle());
194            
195            I18nizableText ed = (I18nizableText) this._script.getParameters().get("page-included-description");
196            return new I18nizableText(ed.getCatalogue(), ed.getKey(), i18nParameters);
197        }
198        else
199        {
200            Map<String, I18nizableTextParameter> i18nParameters = new HashMap<>();
201            i18nParameters.put("title", getSitemapTitle((Sitemap) pageOrSitemap));
202            i18nParameters.put("name", new I18nizableText(pageOrSitemap.getSitemapName()));
203            
204            I18nizableText ed = (I18nizableText) this._script.getParameters().get("sitemap-included-description");
205            return new I18nizableText(ed.getCatalogue(), ed.getKey(), i18nParameters);
206        }
207    }
208
209    private boolean _isExcludedFromSEO (ModelLessDataAwareAmetysObject pageOrSitemap)
210    {
211        return pageOrSitemap.getValue(DefaultPage.METADATA_ROBOTS_DISALLOW, false);
212    }
213    
214    private boolean _isParentExcludedFromSEO (SitemapElement pageOrSitemap)
215    {
216        AmetysObject parent = pageOrSitemap.getParent();
217        while (parent != null && parent instanceof SitemapElement)
218        {
219            boolean excluded = _isExcludedFromSEO((ModelLessDataAwareAmetysObject) parent);
220            if (excluded)
221            {
222                return true;
223            }
224            
225            parent = parent.getParent();
226        }
227        
228        return false;
229    }
230}