001/* 002 * Copyright 2021 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.question.types; 017 018import java.util.Arrays; 019import java.util.HashMap; 020import java.util.List; 021import java.util.Map; 022 023import org.apache.cocoon.xml.XMLUtils; 024import org.apache.commons.lang.StringUtils; 025import org.xml.sax.ContentHandler; 026import org.xml.sax.SAXException; 027 028import org.ametys.plugins.forms.helper.FormElementDefinitionHelper; 029import org.ametys.plugins.forms.question.validators.FileFormValidator; 030import org.ametys.plugins.forms.repository.FormQuestion; 031import org.ametys.runtime.config.Config; 032import org.ametys.runtime.config.DisableCondition; 033import org.ametys.runtime.config.DisableCondition.OPERATOR; 034import org.ametys.runtime.config.DisableConditions; 035import org.ametys.runtime.i18n.I18nizableText; 036import org.ametys.runtime.model.ElementDefinition; 037import org.ametys.runtime.model.ModelItem; 038import org.ametys.runtime.model.SimpleViewItemGroup; 039import org.ametys.runtime.model.StaticEnumerator; 040import org.ametys.runtime.model.ViewElement; 041import org.ametys.runtime.model.type.ModelItemTypeConstants; 042import org.ametys.runtime.parameter.DefaultValidator; 043import org.ametys.runtime.servlet.RuntimeServlet; 044 045/** 046 * Class for creating file questions 047 */ 048public class FileQuestionType extends AbstractFormQuestionType 049{ 050 /** Constant for max size attribute. */ 051 public static final String ATTRIBUTE_MAX_SIZE = "max-size"; 052 053 /** Constant for allowed extensions attribute. */ 054 public static final String ATTRIBUTE_EXTENSIONS = "extensions"; 055 056 /** Constant for other allowed extensions attribute. */ 057 public static final String ATTRIBUTE_EXTENSIONS_OTHER = "extensions-other"; 058 059 /** Constant for default title */ 060 public static final String DEFAULT_TITLE = "PLUGIN_FORMS_QUESTION_DEFAULT_TITLE_FILE"; 061 062 /** Constant for all extensions */ 063 public static final String ALL_EXTENSIONS_VALUE = "_ametys_all_extension"; 064 065 /** Constant for image extensions */ 066 public static final String IMAGE_EXTENSIONS_VALUE = "_ametys_image_extension"; 067 068 /** Constant for video extensions */ 069 public static final String VIDEO_EXTENSIONS_VALUE = "_ametys_video_extension"; 070 071 /** Constant for audio extensions */ 072 public static final String AUDIO_EXTENSIONS_VALUE = "_ametys_audio_extension"; 073 074 /** Constant for document extensions */ 075 public static final String DOCUMENT_EXTENSIONS_VALUE = "_ametys_document_extension"; 076 077 /** Constant for other extensions */ 078 public static final String OTHER_EXTENSIONS_VALUE = "_ametys_other_extension"; 079 080 @Override 081 protected List<ModelItem> _getModelItems() 082 { 083 List<ModelItem> modelItems = super._getModelItems(); 084 085 ElementDefinition<Long> maxSize = FormElementDefinitionHelper.getElementDefinition(ATTRIBUTE_MAX_SIZE, ModelItemTypeConstants.LONG_TYPE_ID, "PLUGINS_FORMS_QUESTIONS_DIALOG_FILE_MAX_SIZE", "PLUGINS_FORMS_QUESTIONS_DIALOG_FILE_MAX_SIZE_DESC", null); 086 087 // Upload initialization 088 long maxSizeValue = _getMaxSizeValue(); 089 maxSize.setWidget("edition.longfield"); 090 Map<String, I18nizableText> widgetParameters = new HashMap<>(); 091 widgetParameters.put("maxValue", new I18nizableText(String.valueOf(maxSizeValue))); 092 widgetParameters.put("minValue", new I18nizableText("1")); 093 widgetParameters.put("emptyText", new I18nizableText(String.valueOf(maxSizeValue))); 094 maxSize.setWidgetParameters(widgetParameters); 095 modelItems.add(maxSize); 096 097 ElementDefinition<String> extensions = FormElementDefinitionHelper.getElementDefinition(ATTRIBUTE_EXTENSIONS, ModelItemTypeConstants.STRING_TYPE_ID, "PLUGINS_FORMS_QUESTIONS_DIALOG_FILE_EXTENSIONS", "PLUGINS_FORMS_QUESTIONS_DIALOG_FILE_EXTENSIONS_DESC", null); 098 099 StaticEnumerator<String> extensionEnum = new StaticEnumerator<>(); 100 extensionEnum.add(new I18nizableText("plugin.forms", "PLUGINS_FORMS_QUESTIONS_DIALOG_FILE_EXTENSIONS_ALL"), ALL_EXTENSIONS_VALUE); 101 extensionEnum.add(new I18nizableText("plugin.forms", "PLUGINS_FORMS_QUESTIONS_DIALOG_FILE_EXTENSIONS_DOCUMENTS"), DOCUMENT_EXTENSIONS_VALUE); 102 extensionEnum.add(new I18nizableText("plugin.forms", "PLUGINS_FORMS_QUESTIONS_DIALOG_FILE_EXTENSIONS_IMAGES"), IMAGE_EXTENSIONS_VALUE); 103 extensionEnum.add(new I18nizableText("plugin.forms", "PLUGINS_FORMS_QUESTIONS_DIALOG_FILE_EXTENSIONS_VIDEO"), VIDEO_EXTENSIONS_VALUE); 104 extensionEnum.add(new I18nizableText("plugin.forms", "PLUGINS_FORMS_QUESTIONS_DIALOG_FILE_EXTENSIONS_AUDIO"), AUDIO_EXTENSIONS_VALUE); 105 extensionEnum.add(new I18nizableText("plugin.forms", "PLUGINS_FORMS_QUESTIONS_DIALOG_FILE_EXTENSIONS_OTHER"), OTHER_EXTENSIONS_VALUE); 106 extensions.setEnumerator(extensionEnum); 107 extensions.setDefaultValue(ALL_EXTENSIONS_VALUE); 108 109 Map<String, I18nizableText> extWidgetParameters = new HashMap<>(); 110 extWidgetParameters.put("naturalOrder", new I18nizableText("true")); 111 extensions.setWidgetParameters(extWidgetParameters); 112 113 modelItems.add(extensions); 114 115 ElementDefinition otherExtensions = FormElementDefinitionHelper.getElementDefinition(ATTRIBUTE_EXTENSIONS_OTHER, ModelItemTypeConstants.STRING_TYPE_ID, "PLUGINS_FORMS_QUESTIONS_DIALOG_FILE_OTHER_EXTENSIONS", "PLUGINS_FORMS_QUESTIONS_DIALOG_FILE_OTHER_EXTENSIONS_DESC", new DefaultValidator("^\\.[a-z0-9]+(,\\s*\\.[a-z0-9]+)*$", false)); 116 DisableConditions disableConditions = new DisableConditions(); 117 DisableCondition condition = new DisableCondition(ATTRIBUTE_EXTENSIONS, OPERATOR.NEQ, "_ametys_other_extension"); 118 disableConditions.getConditions().add(condition); 119 otherExtensions.setDisableConditions(disableConditions); 120 Map<String, I18nizableText> otherExtWidgetParameters = new HashMap<>(); 121 otherExtWidgetParameters.put("ametysShowMultipleHint", new I18nizableText("true")); 122 otherExtensions.setWidgetParameters(otherExtWidgetParameters); 123 modelItems.add(otherExtensions); 124 125 return modelItems; 126 } 127 128 @Override 129 protected SimpleViewItemGroup _getMainTab() 130 { 131 SimpleViewItemGroup mainFieldset = super._getMainTab(); 132 133 ViewElement extensions = new ViewElement(); 134 extensions.setDefinition((ElementDefinition< ? >) getModel().getModelItem(ATTRIBUTE_EXTENSIONS)); 135 mainFieldset.addViewItem(extensions); 136 137 ViewElement otherExtensions = new ViewElement(); 138 otherExtensions.setDefinition((ElementDefinition< ? >) getModel().getModelItem(ATTRIBUTE_EXTENSIONS_OTHER)); 139 mainFieldset.addViewItem(otherExtensions); 140 141 return mainFieldset; 142 } 143 144 @Override 145 protected SimpleViewItemGroup _getAdvancedTab() 146 { 147 SimpleViewItemGroup advancedFieldset = super._getAdvancedTab(); 148 149 ViewElement maxSize = new ViewElement(); 150 maxSize.setDefinition((ElementDefinition< ? >) getModel().getModelItem(ATTRIBUTE_MAX_SIZE)); 151 advancedFieldset.addViewItem(maxSize); 152 153 return advancedFieldset; 154 } 155 156 @Override 157 public void validateQuestionValues(Map<String, Object> values, Map<String, I18nizableText> errors) 158 { 159 super.validateQuestionValues(values, errors); 160 161 Number sizeAsNumber = (Number) values.getOrDefault(ATTRIBUTE_MAX_SIZE, null); 162 Long maxSize = _getMaxSizeValue(); 163 Long size = sizeAsNumber != null ? sizeAsNumber.longValue() : maxSize; 164 if (size > maxSize) 165 { 166 List<String> errorParams = Arrays.asList(String.valueOf(maxSize)); 167 168 errors.put(ATTRIBUTE_MAX_SIZE, new I18nizableText("plugin.forms", "PLUGINS_FORMS_QUESTIONS_DIALOG_FILE_MAXSIZE_ERROR", errorParams)); 169 } 170 } 171 172 private long _getMaxSizeValue() 173 { 174 long maxSizeValue = RuntimeServlet.DEFAULT_MAX_UPLOAD_SIZE; 175 Long maxUploadSizeParam = Config.getInstance().getValue("runtime.upload.max-size"); 176 if (maxUploadSizeParam != null) 177 { 178 maxSizeValue = maxUploadSizeParam.intValue(); 179 } 180 181 return maxSizeValue / (1024 * 1024); 182 } 183 184 public String getStorageType(FormQuestion question) 185 { 186 return org.ametys.cms.data.type.ModelItemTypeConstants.FILE_ELEMENT_TYPE_ID; 187 } 188 189 @Override 190 protected ModelItem _getEntryModelItem(FormQuestion question) 191 { 192 ModelItem item = super._getEntryModelItem(question); 193 ((ElementDefinition) item).setValidator(new FileFormValidator(null, isMandatory(question), question.getValue(ATTRIBUTE_MAX_SIZE, false, _getMaxSizeValue()), _getAllowedExtensions(question))); 194 return item; 195 } 196 197 @Override 198 public void saxAdditionalInfos(ContentHandler contentHandler, FormQuestion question) throws SAXException 199 { 200 super.saxAdditionalInfos(contentHandler, question); 201 202 XMLUtils.createElement(contentHandler, "allowed-extensions", _getAllowedExtensions(question)); 203 204 Long maxSize = question.getValue(ATTRIBUTE_MAX_SIZE, false, _getMaxSizeValue()); 205 XMLUtils.createElement(contentHandler, "max-size", String.valueOf(maxSize)); 206 } 207 208 private String _getAllowedExtensions(FormQuestion question) 209 { 210 String value = question.getValue(ATTRIBUTE_EXTENSIONS, false, ALL_EXTENSIONS_VALUE); 211 switch (value) 212 { 213 case DOCUMENT_EXTENSIONS_VALUE: 214 return ".txt, .pdf, .xls, .xlsx, .doc, .docx, .ptt, .pttx, .odt, .ods, .odp, .odb, .odg, .odf"; 215 case IMAGE_EXTENSIONS_VALUE: 216 return ".png, .gif, .jpg, .jpeg"; 217 case VIDEO_EXTENSIONS_VALUE: 218 return ".mp4, .m4v, .mov, .avi, .flv, .wmv, .mpeg, .mkv"; 219 case AUDIO_EXTENSIONS_VALUE: 220 return ".wav, .wave, .flac, .m4a, .wma, .wmv, .mp3, .ogg, .oga, .mogg, .aac, .aiff, .aif"; 221 case OTHER_EXTENSIONS_VALUE: 222 return question.getValue(ATTRIBUTE_EXTENSIONS_OTHER, false, StringUtils.EMPTY); 223 case ALL_EXTENSIONS_VALUE: 224 default: 225 return StringUtils.EMPTY; 226 } 227 } 228 229 public I18nizableText getDefaultTitle() 230 { 231 return new I18nizableText("plugin.forms", DEFAULT_TITLE); 232 } 233 234 @Override 235 public List<String> getFieldToDisableIfFormPublished(FormQuestion question) 236 { 237 List<String> fieldNames = super.getFieldToDisableIfFormPublished(question); 238 fieldNames.add(ATTRIBUTE_EXTENSIONS); 239 fieldNames.add(ATTRIBUTE_EXTENSIONS_OTHER); 240 return fieldNames; 241 } 242}