View Javadoc
1   /*
2    * Copyright (c) 2002-2021, 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.plugins.newsletter.business.portlet;
35  
36  import fr.paris.lutece.plugins.newsletter.business.NewsLetter;
37  import fr.paris.lutece.plugins.newsletter.business.NewsLetterHome;
38  import fr.paris.lutece.plugins.newsletter.business.NewsLetterProperties;
39  import fr.paris.lutece.plugins.newsletter.business.NewsletterPropertiesHome;
40  import fr.paris.lutece.plugins.newsletter.util.NewsletterUtils;
41  import fr.paris.lutece.portal.business.portlet.Portlet;
42  import fr.paris.lutece.portal.service.captcha.CaptchaSecurityService;
43  import fr.paris.lutece.portal.service.i18n.I18nService;
44  import fr.paris.lutece.portal.service.plugin.Plugin;
45  import fr.paris.lutece.portal.service.plugin.PluginService;
46  import fr.paris.lutece.util.date.DateUtil;
47  import fr.paris.lutece.util.xml.XmlUtil;
48  import org.apache.commons.lang3.StringUtils;
49  
50  import javax.servlet.http.HttpServletRequest;
51  import java.util.*;
52  
53  import static fr.paris.lutece.portal.service.admin.AdminUserService.getLocale;
54  
55  /**
56   * This class represents the business object NewsLetterSubscriptionPortlet.
57   */
58  public class NewsLetterSubscriptionPortlet extends Portlet
59  {
60      // The names of the XML tags
61      private static final String TAG_CDATA_BEGIN = "<![CDATA[";
62      private static final String TAG_CDATA_END = "]]>";
63      private static final String TAG_NEWSLETTER_SUBSCRIPTION_LIST = "newsletter-subscription-list";
64      private static final String TAG_NEWSLETTER_SUBSCRIPTION = "newsletter-subscription";
65      private static final String TAG_NEWSLETTER_SUBSCRIPTION_ID = "newsletter-subscription-id";
66      private static final String TAG_NEWSLETTER_SUBSCRIPTION_EMAIL = "newsletter-subscription-email";
67      private static final String TAG_NEWSLETTER_SUBSCRIPTION_DATE = "newsletter-subscription-date";
68      private static final String TAG_NEWSLETTER_SUBSCRIPTION_DESC = "newsletter-subscription-subject";
69      private static final String TAG_NEWSLETTER_SUBSCRIPTION_BUTTON = "newsletter-subscription-button";
70      private static final String TAG_NEWSLETTER_EMAIL_ERROR = "newsletter-email-error";
71      private static final String TAG_NEWSLETTER_NO_CHOICE_ERROR = "subscription-nochoice-error";
72      private static final String TAG_NEWSLETTER_CAPTCHA = "newsletter-subscription-captcha";
73      private static final String TAG_NEWSLETTER_TOS = "newsletter-subscription-tos";
74      private static final String TAG_NEWSLETTER_TOS_CONTENT = "newsletter-subscription-tos-content";
75      private static final String PROPERTY_LABEL_MAIL = "newsletter.portlet.mail.label";
76      private static final String PROPERTY_LABEL_BUTTON = "newsletter.portlet.button.label";
77      private static final String PROPERTY_ERROR_INVALID_MAIL = "newsletter.message.error.newsletter.invalid.mail";
78      private static final String PROPERTY_ERROR_NO_CHOICE_ERROR = "newsletter.message.error.newsletter.nochoice.error";
79      private static final String PARAMETER_EMAIL_ERROR = "email-error";
80      private static final String PARAMETER_NO_NEWSLETTER_CHOSEN = "nochoice-error";
81      private static final String JCAPTCHA_PLUGIN = "jcaptcha";
82  
83      /**
84       * Comparator for sorting - date descendant order
85       */
86      private static final Comparator<NewsLetter> COMPARATOR_DATE_DESC = new Comparator<NewsLetter>( )
87      {
88          /**
89           * Compare the last sending dates of two newsletters.
90           * 
91           * @param obj1
92           *            The first newsletter
93           * @param obj2
94           *            The second newsletter
95           * @return the value <code>0</code> if the two objects are equal; a value less than <code>0</code> if the first object is before the second; and a value
96           *         greater than <code>0</code> otherwise
97           */
98          public int compare( NewsLetter../../../../../../../fr/paris/lutece/plugins/newsletter/business/NewsLetter.html#NewsLetter">NewsLetter obj1, NewsLetter obj2 )
99          {
100             return obj2.getDateLastSending( ).compareTo( obj1.getDateLastSending( ) );
101         }
102     };
103 
104     // Captcha
105     private CaptchaSecurityService _captchaService;
106     private Plugin _plugin;
107 
108     /**
109      * Sets the name of the plugin associated with this portlet.
110      * 
111      * @param strPluginName
112      *            The plugin name.
113      */
114     public void setPluginName( String strPluginName )
115     {
116         super.setPluginName( strPluginName );
117 
118         // We override this method in order to initialize the plugin instance :
119         this._plugin = PluginService.getPlugin( strPluginName );
120     }
121 
122     /**
123      * Returns the Xml code of the Subscriber portlet with XML heading
124      * 
125      * @param request
126      *            The HTTP servlet request
127      * @return the Xml code of the Subscription portlet
128      */
129     public String getXmlDocument( HttpServletRequest request )
130     {
131         return XmlUtil.getXmlHeader( ) + getXml( request );
132     }
133 
134     /**
135      * Returns the Xml code of the Subscuption portlet without XML heading
136      * 
137      * @param request
138      *            The HTTP servlet request
139      * @return the Xml code of the Subscription portlet content
140      */
141     public String getXml( HttpServletRequest request )
142     {
143         // List listErrors = new ArrayList( );
144         String strMailError = null;
145         String strNoChoiceError = null;
146 
147         if ( request != null )
148         {
149             strMailError = request.getParameter( PARAMETER_EMAIL_ERROR );
150             strNoChoiceError = request.getParameter( PARAMETER_NO_NEWSLETTER_CHOSEN );
151         }
152 
153         if ( StringUtils.isBlank( strMailError ) )
154         {
155             strMailError = StringUtils.EMPTY;
156         }
157 
158         if ( StringUtils.isBlank( strNoChoiceError ) )
159         {
160             strNoChoiceError = StringUtils.EMPTY;
161         }
162 
163         StringBuffer strXml = new StringBuffer( );
164 
165         XmlUtil.beginElement( strXml, TAG_NEWSLETTER_SUBSCRIPTION_LIST );
166 
167         // We need the data of the sendings associated with this portlet.
168         // However, the association table and the sendings table are on two
169         // different datasources (AppConnectionService and
170         // PluginConnectionService respectively). Therefore we can't roll
171         // everything into a single SQL request.
172         // Hence the manual join and ordering below.
173         // Get the ids of the newsletter sendings to display in the portlet.
174         Set<Integer> sendingIds = NewsLetterSubscriptionPortletHome.findSelectedNewsletters( this.getId( ) );
175         Iterator<Integer> iterIds = sendingIds.iterator( );
176 
177         // Read all the sendings from the plugin-specific datasource
178         List<NewsLetter> sendings = new ArrayList<NewsLetter>( );
179 
180         while ( iterIds.hasNext( ) )
181         {
182             int sendingId = iterIds.next( ).intValue( );
183 
184             // Read the content of the sending on the PluginConnectionService :
185             NewsLetter sending = NewsLetterHome.findByPrimaryKey( sendingId, _plugin );
186 
187             sendings.add( sending );
188         }
189 
190         // Then order the sendings by date
191         Collections.sort( sendings, COMPARATOR_DATE_DESC );
192 
193         // Then generate the XML code
194         Iterator<NewsLetter> iterSendings = sendings.iterator( );
195 
196         while ( iterSendings.hasNext( ) )
197         {
198             NewsLetter sending = iterSendings.next( );
199 
200             // Generate the XML code for the sending :
201             XmlUtil.beginElement( strXml, TAG_NEWSLETTER_SUBSCRIPTION );
202             XmlUtil.addElement( strXml, TAG_NEWSLETTER_SUBSCRIPTION_ID, sending.getId( ) );
203             XmlUtil.addElement( strXml, TAG_NEWSLETTER_SUBSCRIPTION_DESC, sending.getName( ) );
204             XmlUtil.addElement( strXml, TAG_NEWSLETTER_SUBSCRIPTION_DATE,
205                     DateUtil.getDateString( sending.getDateLastSending( ), NewsletterUtils.getLocale( request ) ) );
206             XmlUtil.endElement( strXml, TAG_NEWSLETTER_SUBSCRIPTION );
207         }
208 
209         XmlUtil.endElement( strXml, TAG_NEWSLETTER_SUBSCRIPTION_LIST );
210 
211         boolean bIsCaptchaEnabled = PluginService.isPluginEnable( JCAPTCHA_PLUGIN );
212         NewsLetterProperties properties = NewsletterPropertiesHome.find( _plugin );
213 
214         if ( bIsCaptchaEnabled && properties.isCaptchaActive( ) )
215         {
216             _captchaService = new CaptchaSecurityService( );
217             XmlUtil.addElement( strXml, TAG_NEWSLETTER_CAPTCHA, TAG_CDATA_BEGIN + _captchaService.getHtmlCode( ) + TAG_CDATA_END );
218         }
219 
220         if ( StringUtils.isNotEmpty( properties.getTOS( ) ) )
221         {
222             XmlUtil.addElement( strXml, TAG_NEWSLETTER_TOS, "true" );
223             XmlUtil.addElementHtml( strXml, TAG_NEWSLETTER_TOS_CONTENT, properties.getTOS( ) );
224         }
225 
226         if ( request != null )
227         {
228             if ( StringUtils.isNotEmpty( strMailError ) )
229             {
230                 XmlUtil.addElement( strXml, TAG_NEWSLETTER_EMAIL_ERROR, I18nService.getLocalizedString( PROPERTY_ERROR_INVALID_MAIL, getLocale( request ) ) );
231             }
232 
233             if ( StringUtils.isNotEmpty( strNoChoiceError ) )
234             {
235                 XmlUtil.addElement( strXml, TAG_NEWSLETTER_NO_CHOICE_ERROR,
236                         I18nService.getLocalizedString( PROPERTY_ERROR_NO_CHOICE_ERROR, getLocale( request ) ) );
237             }
238 
239             XmlUtil.addElement( strXml, TAG_NEWSLETTER_SUBSCRIPTION_BUTTON, I18nService.getLocalizedString( PROPERTY_LABEL_BUTTON, getLocale( request ) ) );
240             XmlUtil.addElement( strXml, TAG_NEWSLETTER_SUBSCRIPTION_EMAIL, I18nService.getLocalizedString( PROPERTY_LABEL_MAIL, getLocale( request ) ) );
241         }
242 
243         String str = addPortletTags( strXml );
244 
245         return str;
246     }
247 
248     /**
249      * Updates the current instance of the HtmlPortlet object
250      */
251     public void update( )
252     {
253         NewsLetterSubscriptionPortletHome.getInstance( ).update( this );
254     }
255 
256     /**
257      * Removes the current instance of the HtmlPortlet object
258      */
259     public void remove( )
260     {
261         NewsLetterSubscriptionPortletHome.getInstance( ).remove( this );
262     }
263 }