ThemesService.java

  1. /*
  2.  * Copyright (c) 2002-2022, City of Paris
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  *  1. Redistributions of source code must retain the above copyright notice
  10.  *     and the following disclaimer.
  11.  *
  12.  *  2. Redistributions in binary form must reproduce the above copyright notice
  13.  *     and the following disclaimer in the documentation and/or other materials
  14.  *     provided with the distribution.
  15.  *
  16.  *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
  17.  *     contributors may be used to endorse or promote products derived from
  18.  *     this software without specific prior written permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  24.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30.  * POSSIBILITY OF SUCH DAMAGE.
  31.  *
  32.  * License 1.0
  33.  */
  34. package fr.paris.lutece.portal.service.portal;

  35. import fr.paris.lutece.portal.business.style.Theme;
  36. import fr.paris.lutece.portal.service.content.PageData;
  37. import fr.paris.lutece.portal.service.database.AppConnectionService;
  38. import fr.paris.lutece.portal.service.i18n.I18nService;
  39. import fr.paris.lutece.portal.service.plugin.Plugin;
  40. import fr.paris.lutece.portal.service.plugin.PluginService;
  41. import fr.paris.lutece.portal.service.spring.SpringContextService;
  42. import fr.paris.lutece.portal.service.util.AppLogService;
  43. import fr.paris.lutece.portal.service.util.AppPropertiesService;
  44. import fr.paris.lutece.util.ReferenceItem;
  45. import fr.paris.lutece.util.ReferenceList;

  46. import org.apache.commons.lang3.StringUtils;

  47. import org.springframework.beans.factory.BeanDefinitionStoreException;
  48. import org.springframework.beans.factory.CannotLoadBeanClassException;
  49. import org.springframework.beans.factory.NoSuchBeanDefinitionException;

  50. import java.util.ArrayList;
  51. import java.util.Collection;
  52. import java.util.Locale;

  53. import javax.servlet.http.Cookie;
  54. import javax.servlet.http.HttpServletRequest;
  55. import javax.servlet.http.HttpServletResponse;

  56. /**
  57.  * ThemesService
  58.  */
  59. public final class ThemesService
  60. {
  61.     public static final String GLOBAL_THEME = "default";
  62.     private static final String THEME_PLUGIN_NAME = "theme";
  63.     private static final String BEAN_THEME_SERVICE = "theme.themeService";
  64.     private static final String COOKIE_NAME = "theme";
  65.     private static final String THEME_TEST = "theme_test";

  66.     // PROPERTIES
  67.     private static final String PROPERTY_USE_GLOBAL_THEME = "portal.style.label.useGlobalTheme";
  68.     private static final String PROPERTY_DEFAULT_CODE_THEME = "themes.default.code";
  69.     private static final String PROPERTY_DEFAULT_PATH_CSS = "themes.default.css";
  70.     private static final String PROPERTY_DEFAULT_PATH_JS = "themes.default.js";
  71.     private static final String PROPERTY_DEFAULT_PATH_IMAGE = "themes.default.images";
  72.     private static final String PROPERTY_DEFAULT_AUTHOR_URL = "themes.default.author_url";
  73.     private static final String PROPERTY_DEFAULT_AUTHOR = "themes.default.author";
  74.     private static final String PROPERTY_DEFAULT_LICENCE = "themes.default.licence";
  75.     private static final String PROPERTY_DEFAULT_DESCRIPTION = "themes.default.name";
  76.     private static final String PROPERTY_DEFAULT_VERSION = "themes.default.version";

  77.     // MESSAGES
  78.     private static final String MESSAGE_THEME_NOT_AVAILABLE = "Theme service not available.";

  79.     /**
  80.      * Private constructor
  81.      */
  82.     private ThemesService( )
  83.     {
  84.     }

  85.     /**
  86.      * Get the theme code depending of the different priorities. The priorities are :
  87.      * <ol>
  88.      * <li>the theme of test (in case you want to test a page with a specific theme)</li>
  89.      * <li>the theme choosen by the user</li>
  90.      * <li>the global theme : the one choosen in the back office for the whole site</li>
  91.      * <li>the page theme : a theme specified for a page</li>
  92.      * </ol>
  93.      *
  94.      * @param data
  95.      *            The PageData object
  96.      * @param request
  97.      *            The HttpServletRequest
  98.      * @return the theme
  99.      */
  100.     public static Theme getTheme( PageData data, HttpServletRequest request )
  101.     {
  102.         String strTheme = StringUtils.EMPTY;

  103.         // The code_theme of the page
  104.         String strPageTheme = data.getTheme( );

  105.         if ( ( strPageTheme != null ) && ( strPageTheme.compareToIgnoreCase( GLOBAL_THEME ) != 0 ) )
  106.         {
  107.             strTheme = strPageTheme;
  108.         }

  109.         // The theme of the user
  110.         String strUserTheme = getUserTheme( request );

  111.         if ( strUserTheme != null )
  112.         {
  113.             strTheme = strUserTheme;
  114.         }

  115.         // the test theme (choosen for a page to test the different theme from the backoffice theme section)
  116.         String themeTest = request.getParameter( THEME_TEST );

  117.         if ( themeTest != null )
  118.         {
  119.             strTheme = themeTest;
  120.         }

  121.         return getGlobalTheme( strTheme );
  122.     }

  123.     /**
  124.      * Gets the theme selected by the user
  125.      *
  126.      * @param request
  127.      *            The HTTP request
  128.      * @return The theme if available otherwise null
  129.      */
  130.     public static String getUserTheme( HttpServletRequest request )
  131.     {
  132.         try
  133.         {
  134.             IThemeService themeService = getThemeService( );

  135.             return themeService.getUserTheme( request );
  136.         }
  137.         catch( ThemeNotAvailableException e )
  138.         {
  139.             return null;
  140.         }
  141.     }

  142.     /**
  143.      * Sets the users theme using a cookie
  144.      *
  145.      * @param request
  146.      *            The HTTP request
  147.      * @param response
  148.      *            The HTTP response
  149.      * @param strTheme
  150.      *            The Theme code
  151.      */
  152.     public static void setUserTheme( HttpServletRequest request, HttpServletResponse response, String strTheme )
  153.     {
  154.         if ( isValid( strTheme ) )
  155.         {
  156.             Cookie cookie = new Cookie( COOKIE_NAME, strTheme );
  157.             cookie.setSecure( true );
  158.             cookie.setHttpOnly(true);
  159.             response.addCookie( cookie );
  160.         }
  161.     }

  162.     /**
  163.      * Check if a given theme code is among valid known theme codes
  164.      *
  165.      * @param strTheme
  166.      *            The theme
  167.      * @return true if valid
  168.      */
  169.     private static boolean isValid( String strTheme )
  170.     {
  171.         for ( ReferenceItem item : getThemes( ) )
  172.         {
  173.             if ( item.getCode( ).equals( strTheme ) )
  174.             {
  175.                 return true;
  176.             }
  177.         }
  178.         return false;
  179.     }

  180.     /**
  181.      * Returns the global theme
  182.      *
  183.      * @return the global theme
  184.      */
  185.     public static String getGlobalTheme( )
  186.     {
  187.         Theme theme = getGlobalTheme( StringUtils.EMPTY );

  188.         return theme.getCodeTheme( );
  189.     }

  190.     /**
  191.      * Returns the global theme Object
  192.      *
  193.      * @return the global theme Object
  194.      */
  195.     public static Theme getGlobalThemeObject( )
  196.     {
  197.         return getGlobalTheme( StringUtils.EMPTY );
  198.     }

  199.     /**
  200.      * Returns the global theme
  201.      *
  202.      * @param strTheme
  203.      *            The theme
  204.      * @return the global theme
  205.      */
  206.     public static Theme getGlobalTheme( String strTheme )
  207.     {
  208.         Theme theme = null;

  209.         try
  210.         {
  211.             IThemeService themeService = getThemeService( );

  212.             if ( StringUtils.isBlank( strTheme ) )
  213.             {
  214.                 theme = themeService.getGlobalTheme( );
  215.             }
  216.             else
  217.             {
  218.                 theme = themeService.getTheme( strTheme );
  219.             }
  220.         }
  221.         catch( ThemeNotAvailableException e )
  222.         {
  223.             theme = getDefaultTheme( );
  224.         }

  225.         return theme;
  226.     }

  227.     /**
  228.      * Sets the global theme
  229.      *
  230.      * @param strGlobalTheme
  231.      *            The global theme
  232.      */
  233.     public static void setGlobalTheme( String strGlobalTheme )
  234.     {
  235.         IThemeService themeService;

  236.         try
  237.         {
  238.             themeService = getThemeService( );
  239.             themeService.setGlobalTheme( strGlobalTheme );
  240.         }
  241.         catch( ThemeNotAvailableException e )
  242.         {
  243.             AppLogService.info( MESSAGE_THEME_NOT_AVAILABLE );
  244.         }
  245.     }

  246.     /**
  247.      * Returns a reference list which contains all the themes
  248.      *
  249.      * @param locale
  250.      *            The Locale
  251.      * @return a reference list
  252.      */
  253.     public static ReferenceList getPageThemes( Locale locale )
  254.     {
  255.         ReferenceList listThemes = new ReferenceList( );

  256.         try
  257.         {
  258.             IThemeService themeService = getThemeService( );
  259.             listThemes = themeService.getThemes( );
  260.         }
  261.         catch( ThemeNotAvailableException e )
  262.         {
  263.             AppLogService.info( MESSAGE_THEME_NOT_AVAILABLE );
  264.         }

  265.         String strGlobalTheme = I18nService.getLocalizedString( PROPERTY_USE_GLOBAL_THEME, locale );
  266.         listThemes.addItem( GLOBAL_THEME, strGlobalTheme );

  267.         return listThemes;
  268.     }

  269.     /**
  270.      * Get the theme service
  271.      *
  272.      * @return the theme service
  273.      * @throws ThemeNotAvailableException
  274.      *             If the theme is not available
  275.      */
  276.     private static IThemeService getThemeService( ) throws ThemeNotAvailableException
  277.     {
  278.         IThemeService themeService = null;

  279.         if ( !isAvailable( ) )
  280.         {
  281.             throw new ThemeNotAvailableException( );
  282.         }

  283.         try
  284.         {
  285.             themeService = SpringContextService.getBean( BEAN_THEME_SERVICE );
  286.         }
  287.         catch( BeanDefinitionStoreException | NoSuchBeanDefinitionException | CannotLoadBeanClassException e )
  288.         {
  289.             throw new ThemeNotAvailableException( );
  290.         }

  291.         return themeService;
  292.     }

  293.     /**
  294.      * Return the default theme in properties
  295.      *
  296.      * @return the default theme
  297.      */
  298.     private static Theme getDefaultTheme( )
  299.     {
  300.         Theme theme = new Theme( );
  301.         String strCodeTheme = AppPropertiesService.getProperty( PROPERTY_DEFAULT_CODE_THEME );
  302.         String strPathCss = AppPropertiesService.getProperty( PROPERTY_DEFAULT_PATH_CSS );
  303.         String strPathImages = AppPropertiesService.getProperty( PROPERTY_DEFAULT_PATH_IMAGE );
  304.         String strPathJs = AppPropertiesService.getProperty( PROPERTY_DEFAULT_PATH_JS );
  305.         String strThemeAuthor = AppPropertiesService.getProperty( PROPERTY_DEFAULT_AUTHOR );
  306.         String strThemeAuthorUrl = AppPropertiesService.getProperty( PROPERTY_DEFAULT_AUTHOR_URL );
  307.         String strThemeDescription = AppPropertiesService.getProperty( PROPERTY_DEFAULT_DESCRIPTION );
  308.         String strThemeLicence = AppPropertiesService.getProperty( PROPERTY_DEFAULT_LICENCE );
  309.         String strThemeVersion = AppPropertiesService.getProperty( PROPERTY_DEFAULT_VERSION );

  310.         theme.setCodeTheme( strCodeTheme );
  311.         theme.setPathCss( strPathCss );
  312.         theme.setPathImages( strPathImages );
  313.         theme.setPathJs( strPathJs );
  314.         theme.setThemeAuthor( strThemeAuthor );
  315.         theme.setThemeAuthorUrl( strThemeAuthorUrl );
  316.         theme.setThemeDescription( strThemeDescription );
  317.         theme.setThemeLicence( strThemeLicence );
  318.         theme.setThemeVersion( strThemeVersion );

  319.         return theme;
  320.     }

  321.     /**
  322.      * Check if the theme service is available. It must have the following requirement to be available :
  323.      * <ul>
  324.      * <li>The <code>plugin-theme</code> is activated</li>
  325.      * <li>The pool of the <code>plugin-theme</code> is defined</li>
  326.      * </ul>
  327.      *
  328.      * @return true if it is available, false otherwise
  329.      */
  330.     public static boolean isAvailable( )
  331.     {
  332.         Plugin pluginTheme = PluginService.getPlugin( THEME_PLUGIN_NAME );

  333.         return PluginService.isPluginEnable( THEME_PLUGIN_NAME ) && ( pluginTheme.getDbPoolName( ) != null )
  334.                 && !AppConnectionService.NO_POOL_DEFINED.equals( pluginTheme.getDbPoolName( ) );
  335.     }

  336.     /**
  337.      * Create a new theme
  338.      *
  339.      * @param theme
  340.      *            the theme
  341.      * @return The theme
  342.      */
  343.     public static Theme create( Theme theme )
  344.     {
  345.         try
  346.         {
  347.             IThemeService themeService = getThemeService( );

  348.             return themeService.create( theme );
  349.         }
  350.         catch( ThemeNotAvailableException e )
  351.         {
  352.             AppLogService.info( MESSAGE_THEME_NOT_AVAILABLE );

  353.             return null;
  354.         }
  355.     }

  356.     /**
  357.      * Update a theme
  358.      *
  359.      * @param theme
  360.      *            the theme to update
  361.      * @return The updated theme
  362.      */
  363.     public static Theme update( Theme theme )
  364.     {
  365.         try
  366.         {
  367.             IThemeService themeService = getThemeService( );

  368.             return themeService.update( theme );
  369.         }
  370.         catch( ThemeNotAvailableException e )
  371.         {
  372.             AppLogService.info( MESSAGE_THEME_NOT_AVAILABLE );

  373.             return null;
  374.         }
  375.     }

  376.     /**
  377.      * Remove a theme
  378.      *
  379.      * @param strCodeTheme
  380.      *            the code theme
  381.      */
  382.     public static void remove( String strCodeTheme )
  383.     {
  384.         try
  385.         {
  386.             IThemeService themeService = getThemeService( );
  387.             themeService.remove( strCodeTheme );
  388.         }
  389.         catch( ThemeNotAvailableException e )
  390.         {
  391.             AppLogService.info( MESSAGE_THEME_NOT_AVAILABLE );
  392.         }
  393.     }

  394.     /**
  395.      * Get a collection of themes
  396.      *
  397.      * @return a collection of themes
  398.      */
  399.     public static Collection<Theme> getThemesList( )
  400.     {
  401.         Collection<Theme> listThemes = new ArrayList<>( );

  402.         try
  403.         {
  404.             IThemeService themeService = getThemeService( );
  405.             listThemes = themeService.getThemesList( );
  406.         }
  407.         catch( ThemeNotAvailableException e )
  408.         {
  409.             Theme theme = getDefaultTheme( );
  410.             listThemes.add( theme );
  411.         }

  412.         return listThemes;
  413.     }

  414.     /**
  415.      * Get the list of themes as a {@link ReferenceList}
  416.      *
  417.      * @return a {@link ReferenceList}
  418.      */
  419.     public static ReferenceList getThemes( )
  420.     {
  421.         ReferenceList listThemes = new ReferenceList( );

  422.         try
  423.         {
  424.             IThemeService themeService = getThemeService( );
  425.             listThemes = themeService.getThemes( );
  426.         }
  427.         catch( ThemeNotAvailableException e )
  428.         {
  429.             Theme theme = getDefaultTheme( );
  430.             listThemes.addItem( theme.getCodeTheme( ), theme.getThemeDescription( ) );
  431.         }

  432.         return listThemes;
  433.     }

  434.     /**
  435.      * Check if the theme is valid
  436.      *
  437.      * @param strCodeTheme
  438.      *            the code theme
  439.      * @return true if it is valid, false otherwise
  440.      */
  441.     public static boolean isValidTheme( String strCodeTheme )
  442.     {
  443.         boolean bIsValidTheme = false;

  444.         try
  445.         {
  446.             IThemeService themeService = getThemeService( );
  447.             bIsValidTheme = themeService.isValidTheme( strCodeTheme );
  448.         }
  449.         catch( ThemeNotAvailableException e )
  450.         {
  451.             Theme theme = getDefaultTheme( );
  452.             bIsValidTheme = theme.getCodeTheme( ).equals( strCodeTheme );
  453.         }

  454.         return bIsValidTheme;
  455.     }
  456. }