001/* 002 * Copyright 2023 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.forms.actions; 017 018import java.util.List; 019import java.util.Map; 020import java.util.Optional; 021 022import org.apache.avalon.framework.parameters.Parameters; 023import org.apache.avalon.framework.service.ServiceException; 024import org.apache.avalon.framework.service.ServiceManager; 025import org.apache.cocoon.environment.ObjectModelHelper; 026import org.apache.cocoon.environment.Redirector; 027import org.apache.cocoon.environment.Request; 028import org.apache.cocoon.environment.SourceResolver; 029 030import org.ametys.core.right.RightManager.RightResult; 031import org.ametys.plugins.forms.dao.FormEntryDAO; 032import org.ametys.plugins.forms.dao.FormQuestionDAO.FormEntryValues; 033import org.ametys.plugins.forms.helper.FormAdminDashboardHelper; 034import org.ametys.plugins.forms.question.types.FileQuestionType; 035import org.ametys.plugins.forms.repository.Form; 036import org.ametys.plugins.forms.repository.FormEntry; 037import org.ametys.plugins.forms.repository.FormQuestion; 038import org.ametys.plugins.repository.RepositoryConstants; 039import org.ametys.plugins.repository.data.holder.values.UntouchedValue; 040import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector; 041import org.ametys.runtime.i18n.I18nizableText; 042import org.ametys.runtime.model.View; 043 044import com.google.common.collect.ArrayListMultimap; 045import com.google.common.collect.Multimap; 046 047/** 048 * Action to edit the given form entry 049 */ 050public class EditFormEntryAction extends AbstractProcessFormAction 051{ 052 /** The form admin dashboard helper */ 053 protected FormAdminDashboardHelper _formAdminDashboardHelper; 054 055 @Override 056 public void service(ServiceManager smanager) throws ServiceException 057 { 058 super.service(smanager); 059 _formAdminDashboardHelper = (FormAdminDashboardHelper) smanager.lookup(FormAdminDashboardHelper.ROLE); 060 } 061 062 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 063 { 064 Request request = ObjectModelHelper.getRequest(objectModel); 065 // Retrieve the current workspace. 066 String currentWsp = RequestAttributeWorkspaceSelector.getForcedWorkspace(request); 067 try 068 { 069 // Force the workspace. 070 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, RepositoryConstants.DEFAULT_WORKSPACE); 071 072 String entryId = request.getParameter("entryId"); 073 if (entryId == null) 074 { 075 throw new IllegalStateException("Impossible to edit entry. No id provided."); 076 } 077 078 FormEntry entry = _resolver.resolveById(entryId); 079 if (_rightManager.currentUserHasRight(FormEntryDAO.HANDLE_FORMS_ENTRIES_RIGHT_ID, entry) != RightResult.RIGHT_ALLOW || !_formAdminDashboardHelper.hasAvailableActions(entry)) 080 { 081 throw new IllegalAccessError("Can't edit the entry with id '" + entryId + "' without convenient rights."); 082 } 083 084 Optional<Long> currentStepId = Optional.of(_entryDAO.getCurrentStepId(entry)); 085 086 View view = View.of(entry.getModel()); 087 Multimap<String, I18nizableText> formErrors = ArrayListMultimap.create(); 088 089 View filteredEntryView = _getRuleFilteredEntryView(entry.getForm(), view, new FormEntryValues(null, entry), currentStepId); 090 091 Map<String, Object> values = _foAmetysObjectCreationHelper.getFormValues(request, filteredEntryView, "", formErrors); 092 _adaptFormValuesForChoiceList(entry.getForm(), values); 093 _adaptFormValuesForFile(request, entry.getForm(), values); 094 095 formErrors.putAll(_foAmetysObjectCreationHelper.validateValues(values, filteredEntryView)); 096 for (FormQuestion question : entry.getForm().getQuestions()) 097 { 098 if (filteredEntryView.hasModelViewItem(question.getNameForForm())) 099 { 100 question.getType().validateEntryValues(question, values, formErrors, currentStepId); 101 } 102 } 103 104 if (!formErrors.isEmpty()) 105 { 106 request.setAttribute("form", entry.getForm()); 107 request.setAttribute("form-errors", formErrors); 108 return null; 109 } 110 111 entry.synchronizeValues(filteredEntryView, values); 112 _handleComputedValues(entry.getForm().getQuestions(), entry, true); 113 114 entry.saveChanges(); 115 } 116 finally 117 { 118 // Restore context 119 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, currentWsp); 120 } 121 122 return EMPTY_MAP; 123 } 124 125 @Override 126 protected List<FormQuestion> _getRuleFilteredQuestions(Form form, FormEntryValues entryValues, Optional<Long> currentStepId) 127 { 128 // Get only writable questions 129 return _formQuestionDAO.getRuleFilteredQuestions(form, entryValues, currentStepId, true, false); 130 } 131 132 private void _adaptFormValuesForFile(Request request, Form form, Map<String, Object> values) 133 { 134 List<FormQuestion> fileQuestions = form.getQuestions() 135 .stream() 136 .filter(q -> q.getType() instanceof FileQuestionType) 137 .toList(); 138 139 for (FormQuestion question : fileQuestions) 140 { 141 String nameForForm = question.getNameForForm(); 142 String fileInfo = request.getParameter(nameForForm + "-info"); 143 if ("untouched".equals(fileInfo)) 144 { 145 values.put(nameForForm, new UntouchedValue()); 146 } 147 } 148 } 149}