diff --git a/app/views/questionnaire/question_types/info/info.php b/app/views/questionnaire/question_types/info/info.php index 04bae4fa8a391a2a3a37a6975e86d028d8d9fab5..2faf8503e0ca5de12c2b73b358e9521a67e531b5 100644 --- a/app/views/questionnaire/question_types/info/info.php +++ b/app/views/questionnaire/question_types/info/info.php @@ -1,6 +1,6 @@ <?php /** - * @var QuestionnaireQuestion $vote + * @var QuestionnaireInfo $vote */ ?> @@ -9,7 +9,7 @@ <?= Icon::create('info-circle', Icon::ROLE_INFO)->asImg(20) ?> </div> <div class="description"> - <? if (isset($vote->questiondata['url']) && trim($vote->questiondata['url'])) : ?> + <? if ($vote->hasValidURL()) : ?> <iframe <?= is_internal_url($vote->questiondata['url']) ? 'sandbox="allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-presentation allow-scripts"' : '' ?> src="<?= htmlReady($vote->questiondata['url']) ?>"></iframe> <? endif ?> diff --git a/lib/models/QuestionnaireInfo.php b/lib/models/QuestionnaireInfo.php index 0b1493c5d6ba6bd16280b64c68ebd16158187186..ffc09ff0d09cb79b1fbb6b549308aecbdfa4f5e0 100644 --- a/lib/models/QuestionnaireInfo.php +++ b/lib/models/QuestionnaireInfo.php @@ -63,4 +63,15 @@ class QuestionnaireInfo extends QuestionnaireQuestion implements QuestionType { return []; } + + /** + * Return whether a given url is valid. + * @return bool + */ + public function hasValidURL(): bool + { + return !empty($this->questiondata['url']) + && trim($this->questiondata['url']) + && filter_var($this->questiondata['url'], FILTER_VALIDATE_URL); + } } diff --git a/resources/vue/components/questionnaires/QuestionnaireInfoEdit.vue b/resources/vue/components/questionnaires/QuestionnaireInfoEdit.vue index 57d6c1310fe71a089644a3a5aa17befe60c24667..bc5e82970fd72f4909ca2011020c49678214f8de 100644 --- a/resources/vue/components/questionnaires/QuestionnaireInfoEdit.vue +++ b/resources/vue/components/questionnaires/QuestionnaireInfoEdit.vue @@ -2,7 +2,8 @@ <div class="vote_edit"> <label> {{ $gettext('Link eines Videos oder einer anderen Informationsseite (optional)') }} - <input type="text" v-model="val_clone.url" ref="autofocus"> + <input type="url" v-model="val_clone.url" ref="infoUrl" + @input="checkValidity()"> </label> <div class="formpart"> @@ -24,7 +25,7 @@ export default { value: { type: Object, required: false, - default: function () { + default() { return { url: '', description: '' @@ -36,14 +37,26 @@ export default { required: false } }, - data: function () { + data () { return { - val_clone: '' + val_clone: this.value, }; }, - mounted: function () { - this.val_clone = this.value; - this.$refs.autofocus.focus(); + methods: { + checkValidity() { + this.$refs.infoUrl.setCustomValidity(''); + + if (!this.$refs.infoUrl.checkValidity()) { + this.$refs.infoUrl.setCustomValidity( + this.$gettext('Der eingegebene Link ist nicht korrekt und wird nicht angezeigt werden.') + ); + this.$refs.infoUrl.reportValidity(); + } + } + }, + mounted() { + this.$refs.infoUrl.focus(); + this.checkValidity(); }, watch: { value (new_val) {