Skip to content

LUT-29761: Ensure that the resubmitted answers go through the validation control process #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,16 @@ protected boolean isRecordStateValid( ITask task, TaskConfig config, int idHisto
}
return bIsValid;
}

/**
* Check whether the values from the given List of FormQuestionResponse are valid
*
* @param listFormQuestionResponse
* the List of FormQuestionResponse to check
* @return true if all the Responses have valid values, returns false otherwise
*/
protected boolean areFormResponsesValid( List<FormQuestionResponse> listFormQuestionResponse )
{
return _formsTaskService.areFormQuestionResponsesValid( listFormQuestionResponse );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

import java.sql.Date;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
Expand All @@ -43,6 +44,7 @@
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;

import fr.paris.lutece.plugins.forms.business.FormQuestionResponse;
import fr.paris.lutece.plugins.forms.business.FormResponse;
import fr.paris.lutece.plugins.forms.business.Question;
import fr.paris.lutece.plugins.forms.business.QuestionHome;
Expand Down Expand Up @@ -92,6 +94,9 @@ public class CompleteFormResponseService extends AbstractFormResponseService imp
@Inject
private ICompleteFormResponseTaskHistoryService _completeFormResponseTaskHistoryService;

// List of FormQuestionResponse to store the user's new Responses
private List<FormQuestionResponse> _submittedFormResponses;

@Override
public List<Question> findListQuestionUsedCorrectForm( FormResponse formResponse )
{
Expand Down Expand Up @@ -226,7 +231,15 @@ public boolean doEditResponseData( HttpServletRequest request, CompleteFormRespo
return false;
}
List<Question> listQuestions = getListQuestionToEdit( response, completeFormResponse.getListCompleteReponseValues( ) );

// Get the values of the newly submitted Responses
_submittedFormResponses = _formsTaskService.getSubmittedFormQuestionResponses( request, response, listQuestions );
// Check if the new Responses are valid
if ( !areFormResponsesValid( _submittedFormResponses ) )
{
return false;
}
// Reset the content of the List
_submittedFormResponses = Collections.emptyList( );
doEditResponseData( request, response, listQuestions, idTask, idHistory );
return true;
}
Expand Down Expand Up @@ -262,4 +275,10 @@ protected void createTaskHistory( EditableResponse editableResponse, int idTask,

_completeFormResponseTaskHistoryService.create( history );
}

@Override
public List<FormQuestionResponse> getSubmittedFormResponseList( )
{
return _submittedFormResponses;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

import javax.servlet.http.HttpServletRequest;

import fr.paris.lutece.plugins.forms.business.FormQuestionResponse;
import fr.paris.lutece.plugins.forms.business.FormResponse;
import fr.paris.lutece.plugins.forms.business.Question;
import fr.paris.lutece.plugins.genericattributes.business.Entry;
Expand Down Expand Up @@ -162,4 +163,11 @@ public interface ICompleteFormResponseService
* the Response
*/
void doCompleteResponse( CompleteFormResponse completeFormResponse );

/**
* Get the List of FormQuestionResponse containing the new Responses that the user is trying to submit
*
* @return A List of FormQuestionResponse
*/
List<FormQuestionResponse> getSubmittedFormResponseList( );
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

import javax.servlet.http.HttpServletRequest;

import fr.paris.lutece.plugins.forms.business.FormQuestionResponse;
import fr.paris.lutece.plugins.forms.business.FormResponse;
import fr.paris.lutece.plugins.forms.business.Question;
import fr.paris.lutece.plugins.genericattributes.business.Entry;
Expand Down Expand Up @@ -176,4 +177,11 @@ public interface IResubmitFormResponseService
* the Response
*/
void doCompleteResponse( ResubmitFormResponse resubmitFormResponse );

/**
* Get the List of FormQuestionResponse containing the new Responses that the user is trying to submit
*
* @return A List of FormQuestionResponse
*/
List<FormQuestionResponse> getSubmittedFormResponseList( );
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@

import java.sql.Date;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -105,6 +106,9 @@ public class ResubmitFormResponseService extends AbstractFormResponseService imp
@Inject
private IResubmitFormResponseTaskHistoryService _resubmitFormResponseTaskHistoryService;

// List of FormQuestionResponse to store the user's new Responses
private List<FormQuestionResponse> _submittedFormQuestionResponses;

@Override
public ResubmitFormResponse find( int nIdHistory, int nIdTask )
{
Expand Down Expand Up @@ -270,7 +274,15 @@ public boolean doEditResponseData( HttpServletRequest request, ResubmitFormRespo
return false;
}
List<Question> listQuestions = getListQuestionToEdit( response, resubmitFormResponse.getListResubmitReponseValues( ) );

// Get the values of the newly submitted Responses
_submittedFormQuestionResponses = _formsTaskService.getSubmittedFormQuestionResponses( request, response, listQuestions );
// Check if the new Responses are valid
if ( !areFormResponsesValid( _submittedFormQuestionResponses ) )
{
return false;
}
// Reset the content of the List
_submittedFormQuestionResponses = Collections.emptyList( );
doEditResponseData( request, response, listQuestions, idTask, idHistory );
return true;
}
Expand Down Expand Up @@ -307,4 +319,10 @@ public void doCompleteResponse( ResubmitFormResponse resubmitFormResponse )
resubmitFormResponse.setDateCompleted( new Date( System.currentTimeMillis( ) ) );
update( resubmitFormResponse );
}

@Override
public List<FormQuestionResponse> getSubmittedFormResponseList( )
{
return _submittedFormQuestionResponses;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import fr.paris.lutece.plugins.forms.business.Control;
import fr.paris.lutece.plugins.forms.business.ControlHome;
import fr.paris.lutece.plugins.forms.business.ControlType;
import fr.paris.lutece.plugins.forms.business.FormQuestionResponse;
import fr.paris.lutece.plugins.forms.business.FormQuestionResponseHome;
import fr.paris.lutece.plugins.forms.business.FormResponse;
Expand All @@ -52,9 +55,11 @@
import fr.paris.lutece.plugins.forms.business.Step;
import fr.paris.lutece.plugins.forms.service.EntryServiceManager;
import fr.paris.lutece.plugins.forms.service.entrytype.EntryTypeDate;
import fr.paris.lutece.plugins.forms.validation.IValidator;
import fr.paris.lutece.plugins.forms.web.StepDisplayTree;
import fr.paris.lutece.plugins.forms.web.entrytype.DisplayType;
import fr.paris.lutece.plugins.forms.web.entrytype.IEntryDataService;
import fr.paris.lutece.plugins.genericattributes.business.GenericAttributeError;
import fr.paris.lutece.plugins.genericattributes.business.Response;
import fr.paris.lutece.plugins.genericattributes.service.entrytype.AbstractEntryTypeUpload;
import fr.paris.lutece.plugins.genericattributes.service.entrytype.EntryTypeServiceManager;
Expand Down Expand Up @@ -178,6 +183,28 @@ public List<String> buildFormStepDisplayTreeList( HttpServletRequest request, Li
return listFormDisplayTrees;
}

@Override
public List<String> buildFormStepDisplayTree( HttpServletRequest request, List<Step> listStep, List<Question> listQuestionToDisplay,
List<FormQuestionResponse> listFormQuestionResponse, FormResponse formResponse, DisplayType displayType )
{
List<String> listFormDisplayTrees = new ArrayList<>( );

List<Integer> listQuestionToDisplayId = listFormQuestionResponse.stream( ).map( FormQuestionResponse::getQuestion ).map( Question::getId )
.collect( Collectors.toList( ) );

if ( !CollectionUtils.isEmpty( listStep ) )
{
for ( Step step : listStep )
{
int nIdStep = step.getId( );

StepDisplayTree stepDisplayTree = new StepDisplayTree( nIdStep, formResponse, listQuestionToDisplayId );
listFormDisplayTrees.add( stepDisplayTree.getCompositeHtml( request, listFormQuestionResponse, request.getLocale( ), displayType ) );
}
}
return listFormDisplayTrees;
}

@Override
public List<EditableResponse> findChangedResponses( List<EditableResponse> listEditableResponse )
{
Expand Down Expand Up @@ -207,6 +234,7 @@ public List<EditableResponse> createEditableResponses( FormResponse formResponse
IEntryDataService entryDataService = EntryServiceManager.getInstance( ).getEntryDataService( question.getEntry( ).getEntryType( ) );
FormQuestionResponse responseFromForm = entryDataService.createResponseFromRequest( question, request, false );
responseFromForm.setIdFormResponse( formResponse.getId( ) );

FormQuestionResponse responseSaved = findSavedResponse( formResponse, question );

if ( responseSaved == null )
Expand Down Expand Up @@ -364,4 +392,67 @@ public String createPreviousNewValue( FormQuestionResponse responseForm )
}
return value;
}

@Override
public List<FormQuestionResponse> getSubmittedFormQuestionResponses( HttpServletRequest request, FormResponse formResponse, List<Question> listQuestions )
{
List<FormQuestionResponse> submittedFormResponses = new ArrayList<>( );
for ( Question question : listQuestions )
{
IEntryDataService entryDataService = EntryServiceManager.getInstance( ).getEntryDataService( question.getEntry( ).getEntryType( ) );
FormQuestionResponse responseFromForm = entryDataService.createResponseFromRequest( question, request, false );
responseFromForm.setIdFormResponse( formResponse.getId( ) );
submittedFormResponses.add( responseFromForm );
}
return submittedFormResponses;
}

@Override
public boolean areFormQuestionResponsesValid( List<FormQuestionResponse> listFormQuestionResponse )
{
boolean areAllResponsesValid = Boolean.TRUE;

for ( FormQuestionResponse formQuestionResponse : listFormQuestionResponse )
{
if ( !isResponseValid( formQuestionResponse ) )
{
areAllResponsesValid = Boolean.FALSE;
}
}
return areAllResponsesValid;
}

/**
* Check whether the given FormQuestionResponse satisfies the Validator associated with it
*
* @param formQuestionResponse
* the FormQuestionResponse to check
* @return true if the Response is valid, returns false otherwise
*/
private boolean isResponseValid( FormQuestionResponse formQuestionResponse )
{
// Get the list of controls created for this question's validation process
List<Control> listControl = ControlHome.getControlByQuestionAndType( formQuestionResponse.getQuestion( ).getId( ),
ControlType.VALIDATION.getLabel( ) );

// Check that the current response is valid with each associated control
for ( Control control : listControl )
{
IValidator validator = EntryServiceManager.getInstance( ).getValidator( control.getValidatorName( ) );

// If the given response is not valid with a control
if ( !validator.validate( formQuestionResponse, control ) )
{
// Create an error to be displayed
GenericAttributeError error = new GenericAttributeError( );
error.setIsDisplayableError( true );
error.setErrorMessage( control.getErrorMessage( ) );
// Set the error on the response's Entry field
formQuestionResponse.setError( error );

return false;
}
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
*/
package fr.paris.lutece.plugins.workflow.modules.forms.service.task;

import java.util.Collection;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
Expand Down Expand Up @@ -99,6 +100,26 @@ default FormResponse findFormResponseFrom( ResourceHistory resourceHistory )
List<String> buildFormStepDisplayTreeList( HttpServletRequest request, List<Step> listStep, List<Question> listQuestionToDisplay, FormResponse formResponse,
DisplayType displayType );

/**
* Get a List of Strings containing the models and values displayed to the user, for each existing Step
*
* @param request
* the HTTP request
* @param listStep
* the List of Steps being processed
* @param listQuestionToDisplay
* the List of Question that should be resubmitted by the user
* @param listFormQuestionResponse
* the List of new FormQuestionResponse being submitted by the user
* @param formResponse
* the FormResponse being processed
* @param displayType
* the DisplayType used in the template
* @return a List of Strings containing the complete template
*/
List<String> buildFormStepDisplayTree( HttpServletRequest request, List<Step> listStep, List<Question> listQuestionToDisplay,
List<FormQuestionResponse> listFormQuestionResponse, FormResponse formResponse, DisplayType displayType );

/**
* Finds the responses that have changed
*
Expand Down Expand Up @@ -174,4 +195,26 @@ List<String> buildFormStepDisplayTreeList( HttpServletRequest request, List<Step
* @return a value ready to be inserted in history
*/
String createPreviousNewValue( FormQuestionResponse responseForm );

/**
* Get the List of responses being submitted
*
* @param request
* the HTTP request
* @param formResponse
* the FormReponse being submitted
* @param listQuestions
* the List of Question associated with the responses being submitted
* @return a List of FormQuestionResponse containing the new Responses' values
*/
List<FormQuestionResponse> getSubmittedFormQuestionResponses( HttpServletRequest request, FormResponse formResponse, List<Question> listQuestions );

/**
* Check whether the values from the given FormQuestionResponse satisfy the Validators (regEx, file type, etc.) associated with them
*
* @param formQuestionResponses
* the List of FormQuestionResponse to check
* @return true if all the Responses are valid, returns false otherwise
*/
boolean areFormQuestionResponsesValid( List<FormQuestionResponse> formQuestionResponses );
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

import javax.servlet.http.HttpServletRequest;

import fr.paris.lutece.plugins.forms.business.FormQuestionResponse;
import fr.paris.lutece.plugins.forms.business.FormResponse;
import fr.paris.lutece.plugins.forms.business.Question;
import fr.paris.lutece.plugins.forms.business.Step;
Expand All @@ -57,6 +58,7 @@
import fr.paris.lutece.portal.web.xpages.XPage;
import fr.paris.lutece.util.html.HtmlTemplate;
import fr.paris.lutece.util.signrequest.AbstractPrivateKeyAuthenticator;
import io.jsonwebtoken.lang.Collections;

public class CompleteFormResponseApp extends AbstractFormResponseApp<CompleteFormResponse>
{
Expand Down Expand Up @@ -88,15 +90,29 @@ public class CompleteFormResponseApp extends AbstractFormResponseApp<CompleteFor
protected XPage getFormResponseXPage( HttpServletRequest request, CompleteFormResponse completeFormResponse )
{
XPage page = new XPage( );
List<String> listStepDisplayTree;

FormResponse formResponse = _formsTaskService.getFormResponseFromIdHistory( completeFormResponse.getIdHistory( ) );
List<Question> listQuestions = _completeFormResponseService.getListQuestionToEdit( formResponse, completeFormResponse.getListCompleteReponseValues( ) );

List<Step> listStep = listQuestions.stream( ).map( Question::getStep ).map( Step::getId ).distinct( ).map( StepHome::findByPrimaryKey )
.collect( Collectors.toList( ) );

List<String> listStepDisplayTree = _formsTaskService.buildFormStepDisplayTreeList( request, listStep, listQuestions, formResponse,
DisplayType.COMPLETE_FRONTOFFICE );
// Get the List of Responses the user previously tried to submit
List<FormQuestionResponse> formQuestionResponseList = _completeFormResponseService.getSubmittedFormResponseList( );
// If the List is empty, then it is likely the first submission attempt
if ( Collections.isEmpty( formQuestionResponseList ) )
{
// If the List has elements, then the user already tried to submit some Responses.
// We make sure to retrieve their values, as well as the potential errors associated with them
listStepDisplayTree = _formsTaskService.buildFormStepDisplayTreeList( request, listStep, listQuestions, formResponse,
DisplayType.COMPLETE_FRONTOFFICE );
}
else
{
listStepDisplayTree = _formsTaskService.buildFormStepDisplayTree( request, listStep, listQuestions, formQuestionResponseList, formResponse,
DisplayType.COMPLETE_FRONTOFFICE );
}

Map<String, Object> model = initModelFormPage( request, formResponse, listStepDisplayTree );
model.put( MARK_COMPLETE_FORM, completeFormResponse );
Expand Down
Loading