Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • alexander.vorwerk/studip
  • hochschule-wismar/stud-ip
  • tleilax/studip
  • marcus/studip
  • manschwa/studip
  • eberhardt/studip
  • uol/studip
  • pluta/studip
  • thienel/extern-uni-b
  • studip/studip
  • strohm/studip
  • uni-osnabrueck/studip
  • FloB/studip
  • universit-t-rostock/studip
  • Robinyyy/studip
  • jakob.diel/studip
  • HyperSpeeed/studip
  • ann/studip
  • nod3zer0/stud-ip-siple-saml-php-plugin
  • erik.hillmann/studip
20 results
Select Git revision
Show changes
Commits on Source (3398)
Showing
with 6548 additions and 7516 deletions
...@@ -20,3 +20,6 @@ block_comment_start = /* ...@@ -20,3 +20,6 @@ block_comment_start = /*
block_comment_end = */ block_comment_end = */
line_comment = // line_comment = //
quote_type = single quote_type = single
[*.yml]
indent_size = 2
\ No newline at end of file
# MYSQL_HOST=""
# MYSQL_USER=""
# MYSQL_PASSWORD=""
# MYSQL_DATABASE=""
# Enable the next line to display the debug bar in development mode
# DEBUG_BAR=1
# Enable the following to allow opening files from exception displays in your
# editor. Beware: You need to provide a full path for prefix your files since
# the exception only displays the relative path.
#
# Variables being substituted: %{file} and %{line}
#
# EDITOR_URL="phpstorm://open?file=<path-to-your-studip>/%{file}&line=%{line}"
# EDITOR_URL="vscode://file/<path-to-your-studip>/%{file}:%{line}:0
# STUDIP_CACHING_ENABLE=""
# STUDIP_CACHE_IS_SESSION_STORAGE=""
# STUDIP_ENV=""
# STUDIP_MAIL_TRANSPORT=""
# STUDIP_PLUGINS_UPLOAD_ENABLE=""
## You may also change configuration settings from the environment. To do so, prefix the configuration name with
## "STUDIP_CONFIG_". Example for changing the site name:
#
# STUDIP_CONFIG_UNI_NAME_CLEAN="new uni name"
{
"parser": "@babel/eslint-parser",
"parserOptions": {
"sourceType": "module"
},
"env": {
"browser": true,
"es6": true
},
"extends": "eslint:recommended",
"globals": {
"STUDIP": "writable",
"CKEDITOR": "writable",
"$": "writable",
"_": "writable",
"jQuery": "writable"
},
"rules": {
"no-unused-vars": "off",
"no-async-promise-executor": "error",
"no-await-in-loop": "error",
"no-promise-executor-return": "error",
"require-atomic-updates": "error",
"max-nested-callbacks": ["error", 3],
"no-return-await": "error",
"prefer-promise-reject-errors": "error"
}
}
*~ *~
.env
.webpack.* .webpack.*
composer composer
node_modules node_modules
nbproject nbproject
phpstan.neon
.caches/* .caches/*
.reports/* .reports/*
...@@ -20,6 +23,7 @@ data/oer_logos/* ...@@ -20,6 +23,7 @@ data/oer_logos/*
data/upload_doc/* data/upload_doc/*
public/.htaccess public/.htaccess
public/.rnd
public/assets/javascripts/*.js public/assets/javascripts/*.js
public/assets/javascripts/*.js.map public/assets/javascripts/*.js.map
public/assets/stylesheets/*.css public/assets/stylesheets/*.css
...@@ -28,13 +32,10 @@ public/pictures/banner/*.gif ...@@ -28,13 +32,10 @@ public/pictures/banner/*.gif
public/pictures/banner/*.jpeg public/pictures/banner/*.jpeg
public/pictures/banner/*.jpg public/pictures/banner/*.jpg
public/pictures/banner/*.png public/pictures/banner/*.png
public/pictures/course/[0-9a-f]*.png public/pictures/stock-images/*
public/pictures/institute/[0-9a-f]*.png public/pictures/course/*/*.webp
public/pictures/smile/*.gif public/pictures/institute/*/*.webp
public/pictures/smile/*.jpeg public/pictures/user/*/*.webp
public/pictures/smile/*.jpg
public/pictures/smile/*.png
public/pictures/user/[0-9a-f]*.png
public/plugins_packages/* public/plugins_packages/*
tests/_log tests/_log
...@@ -43,5 +44,10 @@ tests/_helpers/TestGuy.php ...@@ -43,5 +44,10 @@ tests/_helpers/TestGuy.php
tests/_helpers/WebGuy.php tests/_helpers/WebGuy.php
tests/_helpers/_generated tests/_helpers/_generated
tests/_output/ tests/_output/
tests/e2e/.auth
tests/e2e/test-results/*
playwright-report/*
.idea .idea
/config/oauth2/*.key
/config/oauth2/encryption_key.php
image: studip/studip:tests image: studip/studip:tests-php8.1
variables: variables:
FF_NETWORK_PER_BUILD: 1
GIT_DEPTH: 1
MYSQL_RANDOM_ROOT_PASSWORD: "true" MYSQL_RANDOM_ROOT_PASSWORD: "true"
MYSQL_DATABASE: studip_db MYSQL_DATABASE: studip_db
MYSQL_USER: studip_user MYSQL_USER: studip_user
...@@ -8,187 +10,381 @@ variables: ...@@ -8,187 +10,381 @@ variables:
MYSQL_HOST: mariadb MYSQL_HOST: mariadb
DEMO_DATA: "true" DEMO_DATA: "true"
MAIL_TRANSPORT: debug MAIL_TRANSPORT: debug
PHPSTAN_LEVEL: 0
# Optimize caching # Optimize caching
FF_USE_FASTZIP: "true" FF_USE_FASTZIP: "true"
CACHE_COMPRESSION_LEVEL: "fast" CACHE_COMPRESSION_LEVEL: "fast"
# User faster docker driver # Use faster docker driver
DOCKER_DRIVER: overlay2 DOCKER_DRIVER: overlay2
# Images
NODE_IMAGE: node:18-slim
# Directories
CACHE_DIR: .caches
REPORT_DIR: .reports
# Set npm cache directory
npm_config_cache: $CI_PROJECT_DIR/.npm
stages: stages:
- build
- checks - checks
- tests - analyse
- test
- cache
- packaging - packaging
- release - release
- build
.scripts: .scripts:
install-composer: mkdir-caches: &mkdir-caches
- mkdir -p $CACHE_DIR
mkdir-reports: &mkdir-reports
- mkdir -p $REPORT_DIR
install-composer: &install-composer
- make composer-dev - make composer-dev
configure-studip: configure-studip: &configure-studip
- !reference [.scripts, install-composer] - *install-composer
- cp docker/studip/config_local.php config/config_local.inc.php - cp docker/studip/config_local.php config/config_local.inc.php
- cp config/config.inc.php.dist config/config.inc.php - cp config/config.inc.php.dist config/config.inc.php
initialize-studip-database: initialize-studip-database: &initialize-studip-database
- !reference [.scripts, configure-studip] - *configure-studip
- chmod +x .gitlab/scripts/install_db.sh - chmod +x .gitlab/scripts/install_db.sh
- .gitlab/scripts/install_db.sh - .gitlab/scripts/install_db.sh
- cli/studip migrate - cli/studip migrate
remove-absolute-path-in-report:
- sed -i "s%$PWD/%%" tests/_output/report.xml
.artifacts:
common: &common-artifacts
when: always
expire_in: 1 week
tests: &test-artifacts
<<: *common-artifacts
paths:
- tests/_output
reports:
junit: tests/_output/report.xml
.caches: .caches:
php: &composer-cache composer: &composer-cache
key: "php-$CI_COMMIT_REF_SLUG" key:
files:
- composer.lock
paths: paths:
- composer/ - composer/
- .caches/phplint-cache policy: pull
js: &npm-cache npm: &npm-cache
key: "js-$CI_COMMIT_REF_SLUG" key:
files:
- package-lock.json
paths: paths:
- node_modules/ - .npm
- .caches/eslint-cache
- .caches/stylelint-cache .definitions:
mariadb-service: &mariadb-service
.only: - name: mariadb:10.2.7
php-changes: &php-changes command: [ "--sql_mode=","--character-set-client=utf8","--character-set-server=utf8","--collation-server=utf8_unicode_ci"]
changes: mysql-service: &mysql-service
- composer.json - name: mysql:8.0
- app/controllers/**/*controller.php command: [ "--sql_mode=","--character-set-server=utf8mb4","--collation-server=utf8mb4_general_ci"]
- db/**/*
- lib/**/* build-composer:
- tests/**/* stage: build
- vendor/**/* needs: []
interruptible: true
variables:
COMPOSER_CACHE: $CACHE_DIR/composer-cache
before_script:
- mkdir -p $COMPOSER_CACHE
script:
- composer install
cache:
- *composer-cache
- key: composer-package-cache
paths:
- $COMPOSER_CACHE
policy: pull-push
lint-php: lint-php:
stage: checks stage: checks
needs: [] needs: [build-composer]
cache: *composer-cache variables:
allow_failure: false CACHE_LOCATION: $CACHE_DIR/phplint-cache
PHPLINT_JSON_REPORT: $REPORT_DIR/phplint-report.json
PHPLINT_CODE_QUALITY_REPORT: $REPORT_DIR/phplint-codequality.json
interruptible: true interruptible: true
cache:
- *composer-cache
- key: "$CI_JOB_NAME_SLUG:$CI_COMMIT_REF_SLUG"
paths:
- $CACHE_LOCATION
before_script: before_script:
- !reference [.scripts, install-composer] - *mkdir-caches
- mkdir -p .reports - *mkdir-reports
- *install-composer
script: script:
- php -d memory_limit=-1 composer/bin/phplint --xml .reports/phplint-report.xml --cache=.caches/phplint-cache - COMPOSER_MEMORY_LIMIT=-1
composer exec phplint
--
--output=$PHPLINT_JSON_REPORT
--format=json
--cache=$CACHE_LOCATION
after_script:
- ./.gitlab/scripts/convert-phplint-report $PHPLINT_JSON_REPORT > $PHPLINT_CODE_QUALITY_REPORT
artifacts:
reports:
codequality: $PHPLINT_CODE_QUALITY_REPORT
lint-php-8.3:
image: studip/studip:tests-php8.3
stage: checks
needs: [build-composer]
variables:
CACHE_LOCATION: $CACHE_DIR/phplint-cache
PHPLINT_JSON_REPORT: $REPORT_DIR/phplint-report-8.3.json
PHPLINT_CODE_QUALITY_REPORT: $REPORT_DIR/phplint-codequality-8.3.json
interruptible: true
cache:
- *composer-cache
- key: "$CI_JOB_NAME_SLUG:$CI_COMMIT_REF_SLUG"
paths:
- $CACHE_LOCATION
before_script:
- *mkdir-caches
- *mkdir-reports
- *install-composer
script:
- COMPOSER_MEMORY_LIMIT=-1
composer exec phplint
--
--output=$PHPLINT_JSON_REPORT
--format=json
--cache=$CACHE_LOCATION
after_script:
- ./.gitlab/scripts/convert-phplint-report $PHPLINT_JSON_REPORT > $PHPLINT_CODE_QUALITY_REPORT
artifacts: artifacts:
<<: *common-artifacts
paths:
- .reports/phplint-report.xml
reports: reports:
junit: .reports/phplint-report.xml codequality: $PHPLINT_CODE_QUALITY_REPORT
lint-js: lint-js:
stage: checks stage: checks
needs: [] needs: []
cache: *npm-cache image: $NODE_IMAGE
allow_failure: false variables:
CACHE_LOCATION: $CACHE_DIR/eslint-cache
ESLINT_CODE_QUALITY_REPORT: $REPORT_DIR/eslint-codequality.json
cache:
- key: "$CI_JOB_NAME_SLUG:$CI_COMMIT_REF_SLUG"
paths:
- $CACHE_LOCATION
interruptible: true interruptible: true
before_script: before_script:
- make npm - *mkdir-reports
- npm ci --prefer--offline
script: script:
- npm run lint -- --cache --cache-location .caches/eslint-cache --format ./node_modules/eslint-junit/index.js - npm run lint-js --
only: --cache --cache-location $CACHE_LOCATION
changes: --format gitlab
- resources/assets/javascripts/**/*
- resources/vue/**/*
artifacts: artifacts:
<<: *common-artifacts
paths:
- .reports/eslint-report.xml
reports: reports:
junit: .reports/eslint-report.xml codequality: $ESLINT_CODE_QUALITY_REPORT
lint-css: lint-css:
stage: checks stage: checks
needs: [] needs: []
cache: *npm-cache image: $NODE_IMAGE
allow_failure: false variables:
CACHE_LOCATION: $CACHE_DIR/stylelint-cache
STYLELINT_CODE_QUALITY_REPORT: $REPORT_DIR/stylelint-codequality.json
interruptible: true interruptible: true
cache:
- key: "CI_COMMIT_REF_SLUG-lint-css"
paths:
- $CACHE_LOCATION
policy: pull-push
when: always
before_script: before_script:
- make npm - *mkdir-caches
- *mkdir-reports
- npm install
script: script:
- npm run css-lint -s -- --cache --cache-location .caches/stylelint-cache --custom-formatter node_modules/stylelint-junit-formatter --output-file .reports/stylelint-report.xml - npm run lint-css --
only: --cache --cache-location $CACHE_LOCATION
changes: --custom-formatter=node_modules/stylelint-formatter-gitlab
- resources/assets/stylesheets/**/* --output-file $STYLELINT_CODE_QUALITY_REPORT
artifacts: artifacts:
<<: *common-artifacts
paths:
- .reports/stylelint-report.xml
reports: reports:
junit: .reports/stylelint-report.xml codequality: $STYLELINT_CODE_QUALITY_REPORT
phpstan:
stage: analyse
needs: [build-composer]
variables:
CACHE_LOCATION: $CACHE_DIR/phpstan
PHPSTAN_CODE_QUALITY_REPORT: $REPORT_DIR/phpstan-codequality.json
interruptible: true
cache:
- *composer-cache
- key: "$CO_JOB_NAME_SLUG:$CI_COMMIT_REF_SLUG"
paths:
- $CACHE_LOCATION
before_script:
- *mkdir-caches
- *mkdir-reports
- *install-composer
- 'echo -e "includes:\n - phpstan.neon.dist\n\nparameters:\n tmpDir: $PHPSTAN_CACHE_PATH" > phpstan.neon'
script:
- php
composer/bin/phpstan analyse
--memory-limit=1G
--no-progress
--level=$PHPSTAN_LEVEL
--error-format=gitlab > $PHPSTAN_CODE_QUALITY_REPORT
after_script:
- rm phpstan.neon
artifacts:
reports:
codequality: $PHPSTAN_CODE_QUALITY_REPORT
test-unit: test-unit:
stage: tests stage: test
needs: [lint-php] needs: [lint-php]
only: *php-changes variables:
PHPUNIT_XML_REPORT: $REPORT_DIR/phpunit-report.xml
cache: cache:
<<: *composer-cache <<: *composer-cache
policy: pull policy: pull
allow_failure: false allow_failure: false
interruptible: true interruptible: true
before_script: before_script:
- !reference [.scripts, configure-studip] - *mkdir-reports
- *configure-studip
script: script:
- composer/bin/codecept run unit --xml - 'composer/bin/codecept
- !reference [.scripts, remove-absolute-path-in-report] run unit
--xml=$PHPUNIT_XML_REPORT
-o "paths: output: ."'
after_script:
- sed -i "s%$PWD/%%" $PHPUNIT_XML_REPORT
artifacts: artifacts:
<<: *test-artifacts reports:
junit: $PHPUNIT_XML_REPORT
test-jest:
stage: test
needs: [lint-js]
image: $NODE_IMAGE
variables:
JS_TEST_REPORT: $REPORT_DIR/jest.xml
cache: *npm-cache
interruptible: true
before_script:
- *mkdir-reports
- npm install
script:
- JEST_JUNIT_OUTPUT_FILE="$JS_TEST_REPORT" npx jest tests/jest/ --ci --reporters=default --reporters=jest-junit
artifacts:
reports:
junit: $JS_TEST_REPORT
test-functional: test-functional:
stage: tests stage: test
needs: [lint-php] needs: [lint-php]
only: *php-changes variables:
FUNCTIONAL_XML_REPORT: $REPORT_DIR/functional-report.xml
FUNCTIONAL_CODE_QUALITY_REPORT: $REPORT_DIR/functional-codequality.json
MYSQL_HOST: mysql
cache: cache:
<<: *composer-cache <<: *composer-cache
policy: pull policy: pull
services: services:
- mariadb - *mysql-service
allow_failure: false allow_failure: false
interruptible: true interruptible: true
before_script: before_script:
- !reference [.scripts, initialize-studip-database] - *mkdir-reports
- *initialize-studip-database
script: script:
- composer/bin/codecept run functional --xml - 'composer/bin/codecept
- !reference [.scripts, remove-absolute-path-in-report] run functional
--xml=$FUNCTIONAL_XML_REPORT
-o "paths: output: ."'
after_script:
- sed -i "s%$PWD/%%" $FUNCTIONAL_XML_REPORT
artifacts: artifacts:
<<: *test-artifacts reports:
junit: $FUNCTIONAL_XML_REPORT
test-jsonapi: test-jsonapi:
stage: tests stage: test
needs: [lint-php] needs: [lint-php]
only: *php-changes
cache: cache:
<<: *composer-cache <<: *composer-cache
policy: pull policy: pull
services: services:
- mariadb - *mariadb-service
allow_failure: false variables:
JSONAPI_XML_REPORT: $REPORT_DIR/jsonapi-report.xml
interruptible: true interruptible: true
before_script: before_script:
- !reference [.scripts, initialize-studip-database] - *mkdir-reports
- *initialize-studip-database
script: script:
- composer/bin/codecept run jsonapi --xml - 'composer/bin/codecept
- !reference [.scripts, remove-absolute-path-in-report] run jsonapi
--xml=$JSONAPI_XML_REPORT
-o "paths: output: ."'
after_script:
- sed -i "s%$PWD/%%" $JSONAPI_XML_REPORT
artifacts: artifacts:
<<: *test-artifacts
when: always
expire_in: 1 week
paths:
- tests/_output
reports: reports:
junit: tests/_output/report.xml junit: $JSONAPI_XML_REPORT
test-assets:
stage: test
needs: []
image: $NODE_IMAGE
cache: *npm-cache
interruptible: true
before_script:
- npm install
script:
- npm run webpack-dev
test-e2e:
stage: test
# needs: [lint-css, lint-js, lint-php]
image: mcr.microsoft.com/playwright:v1.33.0-jammy
services:
- name: mariadb
command: ["--sql_mode="]
variables:
PHP_WEBSERVER_URL: localhost:65432
E2E_REPORT: $REPORT_DIR/e2e.xml
interruptible: true
when: manual
cache:
- *composer-cache
- *npm-cache
before_script:
- mkdir ./bin
- apt-get update
- apt -y install software-properties-common
- add-apt-repository ppa:ondrej/php
- apt-get update
- DEBIAN_FRONTEND=noninteractive
apt-get -yq install
make zip unzip mariadb-client
php7.4 libapache2-mod-php7.4 php7.4-common php7.4-curl php7.4-mbstring
php7.4-xmlrpc php7.4-mysql php7.4-gd php7.4-xml php7.4-intl php7.4-ldap
php7.4-imagick php7.4-json php7.4-cli
- echo "short_open_tag=On" >> /etc/php/7.4/php.ini
- echo "short_open_tag=On" >> /etc/php/7.4/cli/php.ini
- php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
- php composer-setup.php --install-dir=./bin --filename=composer
- export PATH="./bin:$PATH"
- php -r "unlink('composer-setup.php');"
- *mkdir-reports
- *initialize-studip-database
- ./cli/studip config:set SHOW_TERMS_ON_FIRST_LOGIN 0
- npm install playwright
- npm ci
- npx playwright install --with-deps
script:
- php -S $PHP_WEBSERVER_URL -t public -q &
- PHP_SERVER_PID=$!
- PLAYWRIGHT_JUNIT_OUTPUT_NAME="$E2E_REPORT"
PLAYWRIGHT_BASE_URL="http://$PHP_WEBSERVER_URL"
npx playwright test --reporter=junit --grep-invert a11y
- kill -3 $PHP_SERVER_PID
artifacts:
reports:
junit: $E2E_REPORT
packaging: packaging:
stage: packaging stage: packaging
...@@ -201,16 +397,28 @@ packaging: ...@@ -201,16 +397,28 @@ packaging:
script: script:
- echo 'Running packaging job' - echo 'Running packaging job'
- make build clean-npm - make build clean-npm
- zip -r9 .pkg/studip-release-$CI_COMMIT_TAG.zip * - zip -r9 .pkg/studip-$CI_COMMIT_TAG.zip *
- tar -czf .pkg/studip-release-$CI_COMMIT_TAG.tar.gz * - tar -czf .pkg/studip-$CI_COMMIT_TAG.tar.gz *
artifacts: artifacts:
untracked: true
name: 'Stud.IP-Release-$CI_COMMIT_TAG' name: 'Stud.IP-Release-$CI_COMMIT_TAG'
paths: paths:
- .pkg/studip-release.zip - .pkg/studip-$CI_COMMIT_TAG.zip
- .pkg/studip-release.tar.gz - .pkg/studip-$CI_COMMIT_TAG.tar.gz
reports: reports:
dotenv: .packaging.env dotenv: .packaging.env
expire_in: never
build_image:
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
stage: build
when: manual
interruptible: true
variables:
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
script:
- /kaniko/executor --context=dir://${CI_PROJECT_DIR} --dockerfile ${CI_PROJECT_DIR}/docker/studip/Dockerfile --destination ${IMAGE_TAG} --cache=true
release: release:
stage: release stage: release
...@@ -224,14 +432,14 @@ release: ...@@ -224,14 +432,14 @@ release:
- job: packaging - job: packaging
artifacts: true artifacts: true
release: release:
name: "Stud.IP-Release-$CI_COMMIT_TAG" name: "$CI_COMMIT_TAG"
description: "Created using the release" description: "https://gitlab.studip.de/studip/studip/-/blob/${CI_COMMIT_TAG}/ChangeLog"
tag_name: "$CI_COMMIT_TAG" tag_name: "$CI_COMMIT_TAG"
assets: assets:
links: links:
- name: "Stud.IP-Release-$CI_COMMIT_TAG.zip" - name: "studip-$CI_COMMIT_TAG.zip"
url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/jobs/${GE_JOB_ID}/artifacts/.pkg/studip-release-$CI_COMMIT_TAG.zip" url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/jobs/${GE_JOB_ID}/artifacts/.pkg/studip-$CI_COMMIT_TAG.zip"
link_type: package link_type: package
- name: "Stud.IP-Release-$CI_COMMIT_TAG.tar.gz" - name: "studip-$CI_COMMIT_TAG.tar.gz"
url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/jobs/${GE_JOB_ID}/artifacts/.pkg/studip-release-$CI_COMMIT_TAG.tar.gz" url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/jobs/${GE_JOB_ID}/artifacts/.pkg/studip-$CI_COMMIT_TAG.tar.gz"
link_type: package link_type: package
version: 2
updates:
- package-ecosystem: composer
directory: /
schedule:
interval: weekly
labels: []
versioning-strategy: lockfile-only
open-pull-requests-limit: -1
open-security-pull-requests-limit: -1
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
labels: []
versioning-strategy: lockfile-only
open-pull-requests-limit: -1
open-security-pull-requests-limit: -1
...@@ -6,4 +6,4 @@ Welches Problem ist aufgetreten und wie ist es dazu gekommen? (Hilfreich: vorher ...@@ -6,4 +6,4 @@ Welches Problem ist aufgetreten und wie ist es dazu gekommen? (Hilfreich: vorher
Ist der Fehler reproduzierbar? Falls ja, wie. Ist der Fehler reproduzierbar? Falls ja, wie.
/label ~BIEST ~"Version::5.2" /label ~BIEST ~"Version::5.4"
## Barrierefreiheits-Review
### Prüfung auf ausreichenden Kontrast und Kenntlichmachung bei GUI-Elementen
- [ ] Vordergrund- und Hintergrundfarbe haben einen ausreichenden Kontrast.
- Mindestens 4,5:1 bei Text und 3:1 bei Icons, idealerweise 7:1.
- [ ] Links werden passend hervorgehoben.
- Kontrast mindestens 3:1 und mit einer weiteren Hervorhebung.
- Wegen GUI-Richtlinien nur im Fließtext umsetzbar.
- [ ] Die angezeigten Informationen sind auch ohne Farbsehen erkennbar.
### Prüfung auf Tastaturbedienbarkeit von Seitenelementen
- [ ] Interaktive Elemente (Link, Button) sind per TAB erreichbar.
- [ ] Elemente verwenden übliche Tasten zur Bedienung
- Eingabetaste für Links und Buttons.
- Pfeiltasten für Select-Felder und Radio-Buttons.
- Leertaste zum Aktivieren von Checkboxen, Radio-Buttons und zum Öffnen von Select-Feldern.
- [ ] Fokusfallen sind nicht vorhanden
- [ ] Die „natürliche“ Reihenfolge der Fokussierung bleibt erhalten.
- tabindex > 0 wird nicht verwendet.
- [ ] Die Fokussierung wird beim Aufruf von Aktionen nicht zurückgesetzt.
### Prüfung auf Nutzbarkeit von Seitenelementen mit Screenreadern
- [ ] Elemente werden korrekt vorgelesen.
- Button: „Schalter“
- Link: „Link“
- Select-Feld: „Auswahlfeld“/„Auswahlschalter“
- [ ] Icons, die nur Schmuckelemente sind, sind für Screenreader unsichtbar.
- [ ] Icons und Bilder, die eine Information liefern, haben einen Alternativtext, der vorgelesen wird.
- [ ] Vorgelesene Texte referenzieren andere Elemente der Seite ohne Positionsangaben.
- [ ] Anhand des vorgelesenen Textes ist die Struktur der Seite erkennbar.
- [ ] Dopplungen von Text (durch ein Icon neben einem Text) tauchen nicht auf.
## Mängel
- (Hier Mängel auflisten)
/label ~BIEST ~Accessibility ~"Version::5.4"
# Releasearbeiten zur Version x.y
## Vorbereitend
* [ ] Release-Notes leeren
* [ ] Version anpassen
## Zum Release
* [ ] Übersetzung vervollständigen
* [ ] Demo-Daten
* [ ] const DEFAULT_ENV = 'production';
* [ ] history.txt
* [ ] Release-Notes
* [ ] Changelog aktualisieren
#!/usr/bin/env php
<?php
function error(string $error, int $status = 1): void
{
echo trim($error) . "\n";
exit($status);
}
$self = basename($argv[0]);
if ($argc !== 2) {
error("Missing report file, use {$self} <filename>");
}
$report_file = $argv[1];
if (!file_exists($report_file)) {
error("Report file {$report_file} does not exist");
}
if (!is_readable($report_file)) {
error("Report file {$report_file} is not readable");
}
$json = json_decode(file_get_contents($report_file), true);
if ($json === false) {
error("Could not read json contents of {$report_file}");
}
$errors = [];
foreach ($json['errors'] as $error) {
$errors[] = [
'description' => $error['error'],
'fingerprint' => md5("{$error['file_name']}:{$error['line']}"),
'severity' => 'major',
'location' => [
'path' => $error['file_name'],
'lines' => [
'begin' => $error['line'],
],
],
];
}
echo json_encode($errors);
#!/bin/bash #!/bin/bash
set -e set -e
if [ $(mysql -f -u $MYSQL_USER -h $MYSQL_HOST -p$MYSQL_PASSWORD $MYSQL_DATABASE -e "show tables;" --batch | wc -l) -eq 0 ]; then importSQLFile() {
mysql --default-character-set=utf8mb4\
--init-command="SET NAMES UTF8;"\
-u $MYSQL_USER\
-h $MYSQL_HOST\
-p$MYSQL_PASSWORD\
$MYSQL_DATABASE\
< $1
}
if [ $(mysql -u $MYSQL_USER -h $MYSQL_HOST -p$MYSQL_PASSWORD $MYSQL_DATABASE -e "show tables;" --batch | wc -l) -eq 0 ]; then
# Setup mysql database # Setup mysql database
echo "INSTALL DB" echo "INSTALL DB"
mysql -f -u $MYSQL_USER -h $MYSQL_HOST -p$MYSQL_PASSWORD $MYSQL_DATABASE < ./db/studip.sql importSQLFile ./db/studip.sql
echo "INSTALL DEFAULT DATA" echo "INSTALL DEFAULT DATA"
mysql -f -u $MYSQL_USER -h $MYSQL_HOST -p$MYSQL_PASSWORD $MYSQL_DATABASE < ./db/studip_default_data.sql importSQLFile ./db/studip_default_data.sql
mysql -f -u $MYSQL_USER -h $MYSQL_HOST -p$MYSQL_PASSWORD $MYSQL_DATABASE < ./db/studip_resources_default_data.sql importSQLFile ./db/studip_resources_default_data.sql
echo "INSTALL ROOTUSER" echo "INSTALL ROOTUSER"
mysql -f -u $MYSQL_USER -h $MYSQL_HOST -p$MYSQL_PASSWORD $MYSQL_DATABASE < ./db/studip_root_user.sql importSQLFile ./db/studip_root_user.sql
# Check if demodata is required # Check if demodata is required
if [ ! -z $DEMO_DATA ]; then if [ ! -z $DEMO_DATA ]; then
echo "INSTALL DEMODATA" echo "INSTALL DEMODATA"
mysql -f -u $MYSQL_USER -h $MYSQL_HOST -p$MYSQL_PASSWORD $MYSQL_DATABASE < ./db/studip_demo_data.sql importSQLFile ./db/studip_demo_data.sql
echo "INSTALL MVV_DEMODATA" echo "INSTALL MVV_DEMODATA"
mysql -f -u $MYSQL_USER -h $MYSQL_HOST -p$MYSQL_PASSWORD $MYSQL_DATABASE < ./db/studip_mvv_demo_data.sql importSQLFile ./db/studip_mvv_demo_data.sql
echo "INSTALL RESOURCES-DEMODATA" echo "INSTALL RESOURCES-DEMODATA"
mysql -f -u $MYSQL_USER -h $MYSQL_HOST -p$MYSQL_PASSWORD $MYSQL_DATABASE < ./db/studip_resources_demo_data.sql importSQLFile ./db/studip_resources_demo_data.sql
fi fi
echo "INSTALLATION FINISHED" echo "INSTALLATION FINISHED"
......
{ {
"extends": "stylelint-config-standard", "extends": "stylelint-config-standard-scss",
"rules": { "rules": {
"alpha-value-notation": null, "alpha-value-notation": null,
"at-rule-empty-line-before": null, "at-rule-empty-line-before": null,
"at-rule-no-vendor-prefix": null, "at-rule-no-vendor-prefix": null,
"block-closing-brace-empty-line-before": null,
"block-closing-brace-newline-after": null,
"block-closing-brace-newline-before": null,
"block-closing-brace-space-before": null,
"block-no-empty": null, "block-no-empty": null,
"block-opening-brace-newline-after": null,
"block-opening-brace-space-after": null,
"block-opening-brace-space-before": null,
"color-function-notation": null, "color-function-notation": null,
"color-hex-case": null,
"color-hex-length": null, "color-hex-length": null,
"color-no-invalid-hex": null, "color-no-invalid-hex": null,
"comment-empty-line-before": null, "comment-empty-line-before": null,
"comment-whitespace-inside": null, "comment-whitespace-inside": null,
"declaration-bang-space-after": null, "custom-property-empty-line-before": null,
"declaration-bang-space-before": null,
"declaration-block-no-duplicate-properties": null, "declaration-block-no-duplicate-properties": null,
"declaration-block-no-redundant-longhand-properties": null, "declaration-block-no-redundant-longhand-properties": null,
"declaration-block-no-shorthand-property-overrides": null, "declaration-block-no-shorthand-property-overrides": null,
"declaration-block-semicolon-newline-after": null,
"declaration-block-semicolon-space-before": null,
"declaration-block-single-line-max-declarations": null, "declaration-block-single-line-max-declarations": null,
"declaration-block-trailing-semicolon": null,
"declaration-colon-newline-after": null,
"declaration-colon-space-after": null,
"declaration-colon-space-before": null,
"declaration-empty-line-before": null, "declaration-empty-line-before": null,
"font-family-name-quotes": null, "font-family-name-quotes": null,
"font-family-no-missing-generic-family-keyword": null, "font-family-no-missing-generic-family-keyword": null,
"function-comma-space-after": null,
"function-comma-space-before": null,
"function-name-case": null, "function-name-case": null,
"function-no-unknown": null, "function-no-unknown": null,
"function-parentheses-newline-inside": null,
"function-parentheses-space-inside": null,
"function-url-quotes": null, "function-url-quotes": null,
"hue-degree-notation": null, "hue-degree-notation": null,
"indentation": null, "import-notation": "string",
"keyframes-name-pattern": null, "keyframes-name-pattern": null,
"length-zero-no-unit": null, "length-zero-no-unit": null,
"max-empty-lines": null, "media-feature-range-notation": "prefix",
"max-line-length": null,
"media-feature-name-no-vendor-prefix": null, "media-feature-name-no-vendor-prefix": null,
"no-descending-specificity": null, "no-descending-specificity": null,
"no-duplicate-selectors": null, "no-duplicate-selectors": null,
"no-empty-first-line": null,
"no-empty-source": null, "no-empty-source": null,
"no-eol-whitespace": null,
"no-extra-semicolons": null,
"no-invalid-position-at-import-rule": null, "no-invalid-position-at-import-rule": null,
"no-irregular-whitespace": null, "no-irregular-whitespace": null,
"no-missing-end-of-source-newline": null,
"number-leading-zero": null,
"number-max-precision": null, "number-max-precision": null,
"number-no-trailing-zeros": null,
"property-no-vendor-prefix": null, "property-no-vendor-prefix": null,
"rule-empty-line-before": null, "rule-empty-line-before": null,
"selector-attribute-quotes": null, "selector-attribute-quotes": null,
"selector-class-pattern": null, "selector-class-pattern": null,
"selector-combinator-space-after": null,
"selector-combinator-space-before": null,
"selector-descendant-combinator-no-non-space": null,
"selector-id-pattern": null, "selector-id-pattern": null,
"selector-list-comma-newline-after": null,
"selector-no-vendor-prefix": null, "selector-no-vendor-prefix": null,
"selector-not-notation": null, "selector-not-notation": null,
"selector-pseudo-element-colon-notation": null, "selector-pseudo-element-colon-notation": null,
"shorthand-property-no-redundant-values": null, "shorthand-property-no-redundant-values": null,
"string-quotes": null,
"value-keyword-case": null, "value-keyword-case": null,
"value-list-max-empty-lines": null, "value-no-vendor-prefix": null,
"value-no-vendor-prefix": null "custom-property-pattern": [
"^([a-z][a-z0-9]*-+)*[a-z0-9]+$",
{"message": "Expected custom property name to be kebab-case-ish (multiple dashes are allowed"}
],
"scss/at-extend-no-missing-placeholder": null,
"scss/at-mixin-pattern": null,
"scss/dollar-variable-empty-line-before": null,
"scss/dollar-variable-pattern": null,
"scss/double-slash-comment-empty-line-before": null,
"scss/function-unquote-no-unquoted-strings-inside": null,
"scss/no-global-function-names": null
}, },
"overrides": [
{
"files": ["**/*.scss"],
"customSyntax": "postcss-scss",
"rules": {
"at-rule-no-unknown": null
}
},
{
"files": ["**/*.less"],
"customSyntax": "postcss-less"
}
],
"ignoreFiles": [ "ignoreFiles": [
"resource/assets/stylesheets/jquery-ui.structure.css", "resource/assets/stylesheets/jquery-ui.structure.css",
"resources/assets/stylesheets/less/jquery-ui/*",
"resources/assets/stylesheets/vendor/*" "resources/assets/stylesheets/vendor/*"
] ]
} }
Source diff could not be displayed: it is too large. Options to address this: view the blob.
Source diff could not be displayed: it is too large. Options to address this: view the blob.
...@@ -38,7 +38,7 @@ PROJECT_NAME = Stud.IP ...@@ -38,7 +38,7 @@ PROJECT_NAME = Stud.IP
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = 4.0 PROJECT_NUMBER = 6.1
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a
......
...@@ -2,8 +2,8 @@ Die Installation von Stud.IP ist halb so schlimm: ...@@ -2,8 +2,8 @@ Die Installation von Stud.IP ist halb so schlimm:
es müssen lediglich ein paar Dateien kopiert werden und ein paar es müssen lediglich ein paar Dateien kopiert werden und ein paar
Programme laufen ;-) Programme laufen ;-)
Vorausgesetzt wird ein Webserver wie Apache2 oder nginx mit PHP-7.0 Modulen und Vorausgesetzt wird ein Webserver wie Apache2 oder nginx mit PHP-8.1 Modulen und
eine MySQL 5.7.6 Datenbank. eine MySQL 8 oder MariaDB 10.2.2 Datenbank.
Was genau zu tun ist, steht in Was genau zu tun ist, steht in
> doc/de/studip-installation-guide-de-401.pdf > doc/de/studip-installation-guide-de-401.pdf
...@@ -16,4 +16,4 @@ können. ...@@ -16,4 +16,4 @@ können.
Also reinsehen und ausprobieren... Viel Spass damit! Also reinsehen und ausprobieren... Viel Spass damit!
You get in an try out. Have a lot of fun! You get in an try out. Have a lot of fun!
The StudIP Core Group <[info@studip.de](mailto:info@studip.de)> 2022 The StudIP Core Group <[info@studip.de](mailto:info@studip.de)> 2022
\ No newline at end of file
CODECEPT = composer/bin/codecept CODECEPT = composer/bin/codecept
CATALOGS = locale/en/LC_MESSAGES/studip.mo locale/en/LC_MESSAGES/js-resources.json CATALOGS = locale/en/LC_MESSAGES/studip.mo locale/en/LC_MESSAGES/js-resources.json
NPM_BIN = $(shell npm bin)
RESOURCES = $(shell find resources -type f) RESOURCES = $(shell find resources -type f)
PHP_SOURCES = $(shell find app config lib public templates -name '*.php' \( ! -path 'public/plugins_packages/*' -o -path 'public/plugins_packages/core/*' \)) PHP_SOURCES = $(shell find app config lib public templates -name '*.php' \( ! -path 'public/plugins_packages/*' -o -path 'public/plugins_packages/core/*' \))
...@@ -42,9 +41,6 @@ webpack-prod: .webpack.prod ...@@ -42,9 +41,6 @@ webpack-prod: .webpack.prod
webpack-watch: npm webpack-watch: npm
npm run webpack-watch npm run webpack-watch
wds: npm
npm run wds
.webpack.dev: node_modules/.package-lock.json $(RESOURCES) .webpack.dev: node_modules/.package-lock.json $(RESOURCES)
@rm -f .webpack.prod @rm -f .webpack.prod
npm run webpack-dev npm run webpack-dev
...@@ -76,23 +72,37 @@ test-functional: $(CODECEPT) ...@@ -76,23 +72,37 @@ test-functional: $(CODECEPT)
test-jsonapi: $(CODECEPT) test-jsonapi: $(CODECEPT)
$(CODECEPT) run jsonapi $(CODECEPT) run jsonapi
test-e2e: npm
npx playwright test
test-unit: $(CODECEPT) test-unit: $(CODECEPT)
$(CODECEPT) run unit $(CODECEPT) run unit
catalogs: npm $(CATALOGS) catalogs: npm $(CATALOGS)
clean-icons:
find public/assets/images/icons -type f -not -path '*blue*' -delete
optimize-icons: npm optimize-icons: npm
find public/assets/images/icons -type f | xargs -P0 $(NPM_BIN)/svgo -q --config=config/svgo.config.js find public/assets/images/icons/blue -type f | xargs -P0 npx svgo -q --config=config/svgo.config.js
icons: optimize-icons
find public/assets/images/icons/blue -type f -print0 | xargs -0 -n1 -I{} echo 'sed "s/#28497c/#000000/g" {} > {}' | sed 's#icons/blue#icons/black#2' | sh
find public/assets/images/icons/blue -type f -print0 | xargs -0 -n1 -I{} echo 'sed "s/#28497c/#00962d/g" {} > {}' | sed 's#icons/blue#icons/green#2' | sh
find public/assets/images/icons/blue -type f -print0 | xargs -0 -n1 -I{} echo 'sed "s/#28497c/#6e6e6e/g" {} > {}' | sed 's#icons/blue#icons/grey#2' | sh
find public/assets/images/icons/blue -type f -print0 | xargs -0 -n1 -I{} echo 'sed "s/#28497c/#cb1800/g" {} > {}' | sed 's#icons/blue#icons/red#2' | sh
find public/assets/images/icons/blue -type f -print0 | xargs -0 -n1 -I{} echo 'sed "s/#28497c/#ffffff/g" {} > {}' | sed 's#icons/blue#icons/white#2' | sh
find public/assets/images/icons/blue -type f -print0 | xargs -0 -n1 -I{} echo 'sed "s/#28497c/#ffad00/g" {} > {}' | sed 's#icons/blue#icons/yellow#2' | sh
# default rules for gettext handling # default rules for gettext handling
js-%.pot: $(VUE_SOURCES) js-%.pot: $(VUE_SOURCES)
$(NPM_BIN)/gettext-extract --attribute v-translate --output $@ $(VUE_SOURCES) npx gettext-extract --attribute v-translate --output $@ $(VUE_SOURCES)
js-%.po: js-%.pot js-%.po: js-%.pot
msgmerge -qU -C $(dir $@)studip.po $@ $< msgmerge -qU -C $(dir $@)studip.po $@ $<
js-%.json: js-%.po js-%.json: js-%.po
$(NPM_BIN)/gettext-compile --output $@ $< npx gettext-compile --output $@ $<
sed -i~ 's/^{[^{]*//;s/}$$//' $@ sed -i~ 's/^{[^{]*//;s/}$$//' $@
%.pot: $(PHP_SOURCES) %.pot: $(PHP_SOURCES)
......
# Stud.IP v6.1
**dd.mm.jjjj**
## Neue Features
-
## Breaking changes
-
## Security related issues
-
## Deprecated Features
-
## Known Issues
-
RELEASE 5.1.alpha-svn RELEASE 6.1.alpha
<?php
class Accessibility_FormsController extends StudipController
{
protected $with_session = true;
public function before_filter(&$action, &$args)
{
parent::before_filter($action, $args);
if (
Config::get()->REPORT_BARRIER_MODE === 'off'
|| (
Config::get()->REPORT_BARRIER_MODE === 'logged-in'
&& !User::findCurrent()
)
) {
throw new AccessDeniedException();
}
}
public function report_barrier_action()
{
PageLayout::setTitle(_('Barriere melden'));
$this->page = Request::get('page');
$user = User::findCurrent();
$user_salutation = '';
if (!empty($user)) {
if ($user->geschlecht == 1) {
$user_salutation = _('Herr');
} elseif ($user->geschlecht == 2) {
$user_salutation = _('Frau');
} elseif ($user->geschlecht == 3) {
$user_salutation = _('divers');
}
}
$this->form = \Studip\Forms\Form::create();
$this->form->addInput(
new \Studip\Forms\HiddenInput(
'page',
'',
$this->page
)
);
$details_part = new \Studip\Forms\Fieldset(_('Angaben zur gefundenen Barriere'));
$details_part->addInput(
new \Studip\Forms\SelectInput(
'barrier_type',
_('Um welche Art von Barriere handelt es sich?'),
'',
[
'options' => [
_('Inhalte auf dieser Seite (z.B. PDF, Bilder oder Lernmodule)') => _('Inhalte auf dieser Seite (z.B. PDF, Bilder oder Lernmodule)'),
_('Ein Problem mit der Seite selbst oder der Navigation') => _('Ein Problem mit der Seite selbst oder der Navigation'),
_('Sonstiges') => _('Sonstiges')
]
]
)
)->setRequired();
$details_part->addInput(
new \Studip\Forms\TextareaInput(
'barrier_details',
_('Beschreiben Sie die Barriere'),
''
)
)->setRequired();
$this->form->addPart($details_part);
$personal_data_part = new \Studip\Forms\Fieldset(_('Ihre persönlichen Daten'));
$personal_data_part->addText(sprintf('<p>%s</p>', _('Freiwillige Angaben Ihrer Kontaktdaten für etwaige Rückfragen.')));
$personal_data_part->addInput(
new \Studip\Forms\SelectInput(
'salutation',
_('Anrede'),
$user_salutation,
[
'options' => [
_('Keine Angabe') => _('Keine Angabe'),
_('Frau') => _('Frau'),
_('Herr') => _('Herr'),
_('divers') => _('divers')
]
]
)
);
$personal_data_part->addInput(
new \Studip\Forms\TextInput(
'name',
_('Vorname und Nachname'),
$user ? sprintf('%s %s', $user->vorname, $user->nachname) : ''
)
);
$personal_data_part->addInput(
new \Studip\Forms\TextInput(
'phone_number',
_('Telefonnummer'),
$user ? ($user->privatcell ?: $user->privatnr) : ''
)
);
$personal_data_part->addInput(
new \Studip\Forms\TextInput(
'email_address',
_('E-Mail-Adresse'),
$user ? $user->email : ''
)
);
// Add a honeypot value and timestamp
$personal_data_part->addInput(
new \Studip\Forms\TextInput(
'homepage',
_('Homepage'),
'',
[
'aria-hidden' => 'true',
'class' => 'sr-only',
'placeholder' => _('Dieses Feld nicht ausfüllen'),
'title' => _('Dieses Feld nicht ausfüllen'),
]
)
);
$this->form->addInput(
new \Studip\Forms\HiddenInput('time', '', time())
);
$personal_data_part->addText(sprintf('<p>%s</p>',
_('Informationen zum Datenschutz dieses Formulars finden Sie in der Datenschutzerklärung.')));
$privacy_url = Config::get()->PRIVACY_URL;
if (is_internal_url($privacy_url)) {
$personal_data_part->addLink(
_('Datenschutzerklärung lesen'),
URLHelper::getURL($privacy_url, ['cancel_login' => '1']),
Icon::create('link-intern'),
['data-dialog' => 'size=big']
);
} else {
$personal_data_part->addLink(
_('Datenschutzerklärung lesen'),
URLHelper::getURL($privacy_url),
Icon::create('link-extern'),
['target' => '_blank']
);
}
$this->form->addPart($personal_data_part);
$this->form->addPart(new \Studip\Forms\Captcha());
$this->form->setSaveButtonText(_('Barriere melden'));
$this->form->setSaveButtonName('report');
$this->form->setURL($this->report_barrierURL());
$this->form->addStoreCallback(
function ($form, $form_values) {
if (
$form_values['time'] >= time() - 2
|| !empty($form_values['homepage'])
) {
return 0;
}
$recipients = Config::get()->ACCESSIBILITY_RECEIVER_EMAIL;
if (empty($recipients)) {
//Fallback: Use the UNI_CONTACT mail address:
$recipients = [$GLOBALS['UNI_CONTACT']];
}
//Get the sender and their language:
$sender = User::findCurrent();
//Default to the system default language:
$lang = explode('_', Config::get()->DEFAULT_LANGUAGE ?? 'de_DE')[0];
if ($sender) {
//Use the senders language since the choices in the form
//are in their language as well.
$lang = explode('_', getUserLanguage($sender->id))[0];
}
//Format the senders name according to the salutation.
$formatted_name = '';
if ($form_values['salutation'] === _('Keine Angabe')) {
$formatted_name = $form_values['name'];
} elseif ($form_values['salutation'] === _('divers')) {
$formatted_name = sprintf('%s (%s)', $form_values['name'], $form_values['salutation']);
} else {
$formatted_name = sprintf('%s %s', $form_values['salutation'], $form_values['name']);
}
//Build the mail text:
$template = $GLOBALS['template_factory']->open("../locale/{$lang}/LC_MAILS/report_barrier.php");
$template->set_attributes([
'sender' => $sender,
'page' => $form_values['page'],
'barrier_type' => $form_values['barrier_type'],
'barrier_details' => $form_values['barrier_details'],
'formatted_name' => $formatted_name,
'phone_number' => $form_values['phone_number'],
'email_address' => $form_values['email_address']
]);
$mail_text = $template->render();
foreach ($recipients as $mail_address) {
//Send the mail:
$mail = new StudipMail();
$mail->addRecipient($mail_address)
->setReplyToEmail($form_values['email_address'])
->setSubject(_('Meldung einer Barriere in Stud.IP'))
->setBodyText($mail_text)
->send();
}
$form->setSuccessMessage(
_('Ihre Meldung einer Barriere wurde weitergeleitet.') . ' ' .
sprintf(
'<a href="%1$s">%2$s %3$s</a>',
URLHelper::getLink($this->page),
Icon::create('link-intern', ['class' => 'text-bottom']),
_('Zurück')
)
);
return 1;
}
);
$this->form->autoStore();
}
}