Sanitize survey frontend and PDF output

This commit is contained in:
Jürgen Mummert
2026-05-24 17:53:53 +02:00
parent 64fc578d4c
commit 6eec9ec537
6 changed files with 84 additions and 41 deletions
@@ -1,7 +1,7 @@
{% include '@Survey/frontend/_survey_assets.html.twig' %}
{% include '@Survey/frontend/_survey_branding.html.twig' %}
{% set moduleHeadline = headline is iterable ? headline.text|default('') : headline|default('') %}
{% set moduleHeadline = (headline is iterable ? headline.text|default('') : headline|default(''))|striptags|trim %}
<section class="survey-shell survey-grid">
{% if moduleHeadline %}
@@ -60,8 +60,8 @@
<div class="survey-grid">
{% for editor in editors %}
<div>
<strong>{{ [editor.firstname, editor.lastname]|join(' ')|trim ?: editor.email }}</strong><br>
<span>{{ editor.email }}</span>
<strong>{{ ([editor.firstname, editor.lastname]|join(' ')|trim|striptags) ?: (editor.email|striptags|trim) }}</strong><br>
<span>{{ editor.email|striptags|trim }}</span>
</div>
{% else %}
<div>Keine Editoren hinterlegt.</div>
@@ -135,8 +135,8 @@
{% if question.mandatory %}<span class="survey-badge warning">Pflicht</span>{% endif %}
{% if loop.first %}<span class="survey-badge success">Start</span>{% endif %}
</div>
<h4>{{ question.question }}</h4>
<p>{{ question.description ?: 'Keine Zusatzbeschreibung.' }}</p>
<h4>{{ question.question|striptags|trim }}</h4>
<p>{{ (question.description|striptags|trim) ?: 'Keine Zusatzbeschreibung.' }}</p>
{% if not locked %}
<div class="survey-button-row">
<a class="survey-button secondary" href="?survey={{ survey.id }}&question={{ question.id }}">Bearbeiten</a>
@@ -169,9 +169,9 @@
<div class="survey-grid">
{% for condition in conditions %}
<article class="survey-card">
<div><strong>Wenn Antwort = {{ condition.answerValue }}</strong></div>
<div>{{ condition.sourceQuestionLabel ?: ('Frage #' ~ condition.sourceQuestion) }}</div>
<div>weiter zu {{ condition.targetQuestionLabel ?: ('Frage #' ~ condition.targetQuestion) }}</div>
<div><strong>Wenn Antwort = {{ condition.answerValue|striptags|trim }}</strong></div>
<div>{{ (condition.sourceQuestionLabel|striptags|trim) ?: ('Frage #' ~ condition.sourceQuestion) }}</div>
<div>weiter zu {{ (condition.targetQuestionLabel|striptags|trim) ?: ('Frage #' ~ condition.targetQuestion) }}</div>
{% if not locked %}
<div class="survey-button-row">
<a class="survey-button secondary" href="?survey={{ survey.id }}&condition={{ condition.id }}">Bearbeiten</a>
@@ -1,7 +1,7 @@
{% include '@Survey/frontend/_survey_assets.html.twig' %}
{% include '@Survey/frontend/_survey_branding.html.twig' %}
{% set moduleHeadline = headline is iterable ? headline.text|default('') : headline|default('') %}
{% set moduleHeadline = (headline is iterable ? headline.text|default('') : headline|default(''))|striptags|trim %}
<section class="survey-shell survey-grid">
{% if moduleHeadline %}
@@ -23,13 +23,13 @@
{% for survey in surveys %}
<article class="survey-card">
<div class="survey-meta">
<h3>{{ survey.title }}</h3>
<h3>{{ survey.title|striptags|trim }}</h3>
<span class="survey-badge {{ survey.published ? 'success' : 'neutral' }}">{{ survey.published ? 'veroeffentlicht' : 'Entwurf' }}</span>
{% if survey.isLocked %}
<span class="survey-badge warning">gesperrt</span>
{% endif %}
</div>
<p>{{ survey.description ?: 'Keine Beschreibung hinterlegt.' }}</p>
<p>{{ (survey.description|striptags|trim) ?: 'Keine Beschreibung hinterlegt.' }}</p>
<div class="survey-meta">
<span class="survey-badge neutral">{{ survey.questionCount }} Fragen</span>
<span class="survey-badge neutral">{{ survey.answerCount }} Antworten</span>
@@ -1,7 +1,7 @@
{% include '@Survey/frontend/_survey_assets.html.twig' %}
{% include '@Survey/frontend/_survey_branding.html.twig' %}
{% set moduleHeadline = headline is iterable ? headline.text|default('') : headline|default('') %}
{% set moduleHeadline = (headline is iterable ? headline.text|default('') : headline|default(''))|striptags|trim %}
<section class="survey-shell survey-grid">
{% if moduleHeadline %}
@@ -13,10 +13,10 @@
{% elseif survey %}
<article class="survey-card">
<div class="survey-meta">
<h3>{{ survey.title }}</h3>
<h3>{{ survey.title|striptags|trim }}</h3>
{% if progress.total > 0 %}<span class="survey-badge neutral">{{ progress.current }}/{{ progress.total }}</span>{% endif %}
</div>
<p>{{ survey.description ?: 'Bitte beantworten Sie die folgenden Fragen. Jede Frage wird einzeln angezeigt.' }}</p>
<p>{{ (survey.description|striptags|trim) ?: 'Bitte beantworten Sie die folgenden Fragen. Jede Frage wird einzeln angezeigt.' }}</p>
{% if progress.total > 0 %}
<div class="survey-progress"><span style="width: {{ progress.percentage }}%"></span></div>
@@ -32,8 +32,8 @@
{% for answer in answers %}
<article class="survey-card">
<div class="survey-badge neutral">{{ answer.questionType }}</div>
<h4>{{ answer.question }}</h4>
<p>{{ answer.value }}</p>
<h4>{{ answer.question|striptags|trim }}</h4>
<p>{{ answer.value|striptags|trim }}</p>
</article>
{% endfor %}
</div>
@@ -42,8 +42,8 @@
{% elseif question %}
<article class="survey-card">
<div class="survey-meta"><span class="survey-badge neutral">Frage {{ progress.current }}</span></div>
<h3>{{ question.question }}</h3>
{% if question.description %}<p>{{ question.description }}</p>{% endif %}
<h3>{{ question.question|striptags|trim }}</h3>
{% if question.description|striptags|trim %}<p>{{ question.description|striptags|trim }}</p>{% endif %}
{{ form_start(surveyForm, {attr: {class: 'survey-form-grid'}}) }}
<input type="hidden" name="REQUEST_TOKEN" value="{{ contao.request_token }}">
@@ -51,7 +51,7 @@
<div class="survey-grid" style="grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));">
{% for child in surveyForm.answer %}
<label class="survey-card" style="cursor: pointer;">
<div class="survey-meta"><strong>{{ child.vars.label }}</strong>{{ form_widget(child) }}</div>
<div class="survey-meta"><strong>{{ child.vars.label|striptags|trim }}</strong>{{ form_widget(child) }}</div>
<div>Diese Antwort wird direkt fuer den weiteren Ablauf verwendet.</div>
</label>
{% endfor %}
@@ -60,7 +60,7 @@
<div class="survey-grid" style="grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));">
{% for child in surveyForm.answer %}
<label class="survey-card" style="cursor: pointer;">
<div class="survey-meta"><strong>{{ child.vars.label }}</strong>{{ form_widget(child) }}</div>
<div class="survey-meta"><strong>{{ child.vars.label|striptags|trim }}</strong>{{ form_widget(child) }}</div>
</label>
{% endfor %}
</div>
@@ -1,7 +1,7 @@
{% include '@Survey/frontend/_survey_assets.html.twig' %}
{% include '@Survey/frontend/_survey_branding.html.twig' %}
{% set moduleHeadline = headline is iterable ? headline.text|default('') : headline|default('') %}
{% set moduleHeadline = (headline is iterable ? headline.text|default('') : headline|default(''))|striptags|trim %}
<section class="survey-shell survey-grid">
{% if moduleHeadline %}
@@ -15,12 +15,12 @@
{% elseif survey %}
<article class="survey-card">
<div class="survey-meta">
<h2>{{ survey.title }}</h2>
<h2>{{ survey.title|striptags|trim }}</h2>
<span class="survey-badge neutral">{{ completedSubmissionCount }} abgeschlossene Teilnahmen</span>
<span class="survey-badge neutral">{{ questionResults|length }} Fragen</span>
</div>
<p>{{ survey.description ?: 'Keine Beschreibung hinterlegt.' }}</p>
<p>{{ (survey.description|striptags|trim) ?: 'Keine Beschreibung hinterlegt.' }}</p>
{% if downloadUrl or pdfDownloadUrl %}
<div class="survey-button-row">
@@ -38,13 +38,13 @@
{% for question in questionResults %}
<article class="survey-card survey-results-card">
<div class="survey-meta">
<h3>{{ question.question }}</h3>
<h3>{{ question.question|striptags|trim }}</h3>
<span class="survey-badge neutral">{{ question.totalAnswers }} Antworten</span>
<span class="survey-badge neutral">{{ question.responseRate }}% Ruecklauf</span>
</div>
{% if question.description %}
<p>{{ question.description }}</p>
{% if question.description|striptags|trim %}
<p>{{ question.description|striptags|trim }}</p>
{% endif %}
<div class="survey-results-layout{% if not question.chart %} no-chart{% endif %}">
@@ -62,7 +62,7 @@
{% for option in question.options %}
<div class="survey-results-row">
<div class="survey-meta">
<strong>{{ option.label }}</strong>
<strong>{{ option.label|striptags|trim }}</strong>
<span class="survey-badge neutral">{{ option.count }}</span>
<span class="survey-badge neutral">{{ option.percentage }}%</span>
</div>
@@ -92,7 +92,7 @@
{% for option in question.distribution %}
<div class="survey-results-row">
<div class="survey-meta">
<strong>{{ option.label }}</strong>
<strong>{{ option.label|striptags|trim }}</strong>
<span class="survey-badge neutral">{{ option.count }}</span>
<span class="survey-badge neutral">{{ option.percentage }}%</span>
</div>
@@ -110,7 +110,7 @@
{% for option in question.responseSummary %}
<div class="survey-results-row">
<div class="survey-meta">
<strong>{{ option.label }}</strong>
<strong>{{ option.label|striptags|trim }}</strong>
<span class="survey-badge neutral">{{ option.count }}</span>
<span class="survey-badge neutral">{{ option.percentage }}%</span>
</div>
@@ -124,7 +124,7 @@
<div class="survey-results-list survey-results-responses">
{% for response in question.responses %}
<blockquote class="survey-card survey-response-card">{{ response|nl2br }}</blockquote>
<blockquote class="survey-card survey-response-card">{{ response|striptags|trim|nl2br }}</blockquote>
{% else %}
<p>Noch keine Freitextantworten vorhanden.</p>
{% endfor %}