001/*
002 *  Copyright 2011 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.plugins.blog.ui;
017
018import java.util.ArrayList;
019import java.util.Arrays;
020import java.util.HashMap;
021import java.util.List;
022import java.util.Map;
023
024import javax.jcr.Node;
025import javax.jcr.RepositoryException;
026import javax.jcr.Value;
027
028import org.apache.avalon.framework.service.ServiceException;
029import org.apache.avalon.framework.service.ServiceManager;
030import org.apache.jackrabbit.value.StringValue;
031
032import org.ametys.core.observation.Event;
033import org.ametys.core.observation.ObservationManager;
034import org.ametys.core.ui.Callable;
035import org.ametys.core.ui.StaticClientSideElement;
036import org.ametys.core.user.CurrentUserProvider;
037import org.ametys.plugins.blog.BlogPageHandler;
038import org.ametys.plugins.blog.repository.BlogRootPageFactory;
039import org.ametys.plugins.repository.AmetysObjectResolver;
040import org.ametys.plugins.repository.jcr.JCRAmetysObject;
041import org.ametys.runtime.i18n.I18nizableText;
042import org.ametys.web.ObservationConstants;
043import org.ametys.web.repository.page.Page;
044import org.ametys.web.repository.page.PagesContainer;
045import org.ametys.web.repository.sitemap.Sitemap;
046
047/**
048 * This element creates an action button to set the blog root page.
049 */
050public class BlogRootClientSideElement extends StaticClientSideElement
051{
052    /** The ametys object resolver. */
053    protected AmetysObjectResolver _resolver;
054
055    /** The blog cache manager. */
056    protected BlogPageHandler _blogRootPageHandler;
057
058    private ObservationManager _observationManager;
059    
060    @Override
061    public void service(ServiceManager serviceManager) throws ServiceException
062    {
063        super.service(serviceManager);
064        _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE);
065        _blogRootPageHandler = (BlogPageHandler) serviceManager.lookup(BlogPageHandler.ROLE);
066        _observationManager = (ObservationManager) serviceManager.lookup(ObservationManager.ROLE);
067        _currentUserProvider = (CurrentUserProvider) serviceManager.lookup(CurrentUserProvider.ROLE);
068    }
069    
070    /**
071     * Get the privacy status of contents
072     * @param pageId the id of contents
073     * @return the privacy status
074     */
075    @Callable
076    public Map<String, Object> getStatus (String pageId)
077    {
078        Map<String, Object> result = new HashMap<>();
079        
080        PagesContainer pageCt = _resolver.resolveById(pageId);
081        result.put("id", pageCt.getId());
082        
083        if (pageCt instanceof JCRAmetysObject)
084        {
085            if (_blogRootPageHandler.isBlogRootPage((JCRAmetysObject) pageCt))
086            {
087                result.put("is-root", true);
088                result.put("blog-page-description", _getBlogRootPageDescription (pageCt));
089                result.put("description", _getRemoveBlogRootPageDescription (pageCt));
090            }
091            else
092            {
093                result.put("description", _getAddBlogRootPageDescription (pageCt));
094            }
095        }
096        else
097        {
098            result.put("no-modifiable", true);
099            result.put("description", _getNoJcrPageDescription ((Page) pageCt));
100        }
101        return result;
102    }
103    
104    
105    /**
106     * Get the Blog root page for the specified site and sitemap
107     * @param siteName The name of the site
108     * @param sitemapName The name of the sitemap
109     * @return The page id
110     */
111    @Callable
112    public String getBlogRootPage(String siteName, String sitemapName)
113    {
114        PagesContainer blogRootPage = _blogRootPageHandler.getBlogRootPage(siteName, sitemapName);
115        if (blogRootPage != null)
116        {
117            return blogRootPage.getId();
118        }
119        
120        return null;
121    }
122    
123    /**
124     * Set the root page for the blog
125     * @param siteName The name of the site
126     * @param sitemapName The name of the sitemap
127     * @param pageId The page id for the new root
128     * @return the new root id and the old root id if exist
129     * @throws RepositoryException if an error occurs
130     */
131    @Callable
132    public Map<String, Object> setBlogRootPage(String siteName, String sitemapName, String pageId) throws RepositoryException
133    {
134        Map<String, Object> result = new HashMap<>();
135        
136        PagesContainer blogRootPage = _blogRootPageHandler.getBlogRootPage(siteName, sitemapName);
137        
138        if (blogRootPage != null)
139        {
140            removeBlogRootPage(blogRootPage.getId());
141            result.put("oldRootId", blogRootPage.getId());
142        }
143        
144        PagesContainer page = _resolver.resolveById(pageId);
145        
146        if (page instanceof JCRAmetysObject)
147        {
148            JCRAmetysObject jcrPage = (JCRAmetysObject) page;
149            Node node = jcrPage.getNode();
150            
151            Value[] values = new Value[]{};
152            if (node.hasProperty(AmetysObjectResolver.VIRTUAL_PROPERTY))
153            {
154                values = node.getProperty(AmetysObjectResolver.VIRTUAL_PROPERTY).getValues();
155            }
156            
157            String blogRoot = BlogRootPageFactory.class.getName();
158            
159            List<Value> valuesAsList = new ArrayList<>(Arrays.asList(values));
160            
161            int index = indexOf(values, blogRoot);
162            if (index < 0)
163            {
164                valuesAsList.add(new StringValue(blogRoot));
165
166                node.setProperty(AmetysObjectResolver.VIRTUAL_PROPERTY, valuesAsList.toArray(new Value[valuesAsList.size()]));
167                jcrPage.saveChanges();
168                
169                result.put("rootId", jcrPage.getId());
170                
171                if (page instanceof Sitemap)
172                {
173                    Map<String, Object> eventParams = new HashMap<>();
174                    eventParams.put(ObservationConstants.ARGS_SITEMAP, page);
175                    _observationManager.notify(new Event(ObservationConstants.EVENT_SITEMAP_UPDATED, _currentUserProvider.getUser(), eventParams));
176                }
177                else if (page instanceof Page)
178                {
179                    Map<String, Object> eventParams = new HashMap<>();
180                    eventParams.put(ObservationConstants.ARGS_PAGE, page);
181                    _observationManager.notify(new Event(ObservationConstants.EVENT_PAGE_CHANGED, _currentUserProvider.getUser(), eventParams));
182                }
183                
184                _blogRootPageHandler.clearCache(page.getSiteName(), page.getSitemapName());
185            }
186        }
187        
188        return result;
189    }    
190    /**
191     * Remove the root page property for the specified page
192     * @param pageId The root page id
193     * @throws RepositoryException if an error occurs
194     */
195    @Callable
196    public void removeBlogRootPage(String pageId) throws RepositoryException
197    {
198        PagesContainer page = _resolver.resolveById(pageId);
199        
200        if (page instanceof JCRAmetysObject)
201        {
202            JCRAmetysObject jcrPage = (JCRAmetysObject) page;
203            Node node = jcrPage.getNode();
204            
205            Value[] values = new Value[]{};
206            if (node.hasProperty(AmetysObjectResolver.VIRTUAL_PROPERTY))
207            {
208                values = node.getProperty(AmetysObjectResolver.VIRTUAL_PROPERTY).getValues();
209            }
210            
211            String blogRoot = BlogRootPageFactory.class.getName();
212            
213            List<Value> valuesAsList = new ArrayList<>(Arrays.asList(values));
214            
215            int index = indexOf(values, blogRoot);
216            if (index >= 0)
217            {
218                valuesAsList.remove(index);
219
220                node.setProperty(AmetysObjectResolver.VIRTUAL_PROPERTY, valuesAsList.toArray(new Value[valuesAsList.size()]));
221                jcrPage.saveChanges();
222                
223                if (page instanceof Sitemap)
224                {
225                    Map<String, Object> eventParams = new HashMap<>();
226                    eventParams.put(ObservationConstants.ARGS_SITEMAP, page);
227                    _observationManager.notify(new Event(ObservationConstants.EVENT_SITEMAP_UPDATED, _currentUserProvider.getUser(), eventParams));
228                }
229                else if (page instanceof Page)
230                {
231                    Map<String, Object> eventParams = new HashMap<>();
232                    eventParams.put(ObservationConstants.ARGS_PAGE, page);
233                    _observationManager.notify(new Event(ObservationConstants.EVENT_PAGE_CHANGED, _currentUserProvider.getUser(), eventParams));
234                }
235                
236                _blogRootPageHandler.clearCache(page.getSiteName(), page.getSitemapName());
237            }
238        }
239    }
240    
241    /**
242     * Tests if an array of JCR Value contains a String value.
243     * @param values the JCR Value array.
244     * @param value the string value to test.
245     * @return the index of the Value if present, -1 otherwise.
246     * @throws RepositoryException if a repository error occurs.
247     */
248    protected int indexOf(Value[] values, String value) throws RepositoryException
249    {
250        int index = -1;
251        
252        for (int i = 0; i < values.length && index < 0; i++)
253        {
254            if (values[i].getString().equals(value))
255            {
256                index = i;
257            }
258        }
259        
260        return index;
261    }
262    
263    /**
264     * Get the default page's parameters
265     * @param pageCt The page container
266     * @return The default parameters
267     */
268    protected Map<String, Object> getPageDefaultParameters (PagesContainer pageCt)
269    {
270        Map<String, Object> pageParams = new HashMap<>();
271        pageParams.put("id", pageCt.getId());
272        
273        return pageParams;
274    }
275    
276    private I18nizableText _getBlogRootPageDescription (PagesContainer pageCt)
277    {
278        if (pageCt instanceof Page)
279        {
280            List<String> i18nParameters = new ArrayList<>();
281            i18nParameters.add(((Page) pageCt).getTitle());
282            
283            I18nizableText ed = (I18nizableText) this._script.getParameters().get("blog-page-description");
284            return new I18nizableText(ed.getCatalogue(), ed.getKey(), i18nParameters);
285        }
286        else
287        {
288            I18nizableText ed = (I18nizableText) this._script.getParameters().get("blog-sitemap-description");
289            return new I18nizableText(ed.getCatalogue(), ed.getKey());
290        }
291    }
292    
293    private I18nizableText _getAddBlogRootPageDescription (PagesContainer pageCt)
294    {
295        if (pageCt instanceof Page)
296        {
297            List<String> i18nParameters = new ArrayList<>();
298            i18nParameters.add(((Page) pageCt).getTitle());
299            
300            I18nizableText ed = (I18nizableText) this._script.getParameters().get("add-blog-page-description");
301            return new I18nizableText(ed.getCatalogue(), ed.getKey(), i18nParameters);
302        }
303        else
304        {
305            I18nizableText ed = (I18nizableText) this._script.getParameters().get("add-blog-sitemap-description");
306            return new I18nizableText(ed.getCatalogue(), ed.getKey());
307        }
308    }
309    
310    private I18nizableText _getRemoveBlogRootPageDescription (PagesContainer pageCt)
311    {
312        if (pageCt instanceof Page)
313        {
314            List<String> i18nParameters = new ArrayList<>();
315            i18nParameters.add(((Page) pageCt).getTitle());
316            
317            I18nizableText ed = (I18nizableText) this._script.getParameters().get("remove-blog-page-description");
318            return new I18nizableText(ed.getCatalogue(), ed.getKey(), i18nParameters);
319        }
320        else
321        {
322            I18nizableText ed = (I18nizableText) this._script.getParameters().get("remove-blog-sitemap-description");
323            return new I18nizableText(ed.getCatalogue(), ed.getKey());
324        }
325    }
326    
327    private I18nizableText _getNoJcrPageDescription (Page page)
328    {
329        List<String> i18nParameters = new ArrayList<>();
330        i18nParameters.add(page.getTitle());
331        
332        I18nizableText ed = (I18nizableText) this._script.getParameters().get("no-jcr-page-description");
333        return new I18nizableText(ed.getCatalogue(), ed.getKey(), i18nParameters);
334    }
335}