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

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
19 results
Show changes
Commits on Source (1422)
Showing
with 1543 additions and 399 deletions
......@@ -20,3 +20,6 @@ block_comment_start = /*
block_comment_end = */
line_comment = //
quote_type = single
[*.yml]
indent_size = 2
\ No newline at end of file
# MYSQL_HOST=""
# MYSQL_USER=""
# MYSQL_PASSWORD=""
# MYSQL_DATABASE=""
# DEBUG_BAR="1" // Enable to display the debug bar in development mode
# 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"
{
"parserOptions": {
"parser": "@typescript-eslint/parser",
"sourceType": "module"
},
"env": {
"browser": true,
"es6": true
},
"extends": [
"eslint:recommended",
"plugin:vue/essential",
"@vue/eslint-config-typescript"
],
"globals": {
"STUDIP": "writable",
"CKEDITOR": "writable",
"$": "writable",
"_": "writable",
"jQuery": "writable"
},
"plugins": [
"vue"
],
"rules": {
"no-unused-vars": "off",
"@typescript-eslint/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", 4],
"no-return-await": "error",
"prefer-promise-reject-errors": "error",
"vue/multi-word-component-names": "off"
}
}
......@@ -23,6 +23,7 @@ data/oer_logos/*
data/upload_doc/*
public/.htaccess
public/.rnd
public/assets/javascripts/*.js
public/assets/javascripts/*.js.map
public/assets/stylesheets/*.css
......
image: studip/studip:tests-php8.2
image: studip/studip:tests-php8.1
variables:
FF_NETWORK_PER_BUILD: 1
......@@ -17,7 +17,7 @@ variables:
# Use faster docker driver
DOCKER_DRIVER: overlay2
# Images
NODE_IMAGE: node:16-slim
NODE_IMAGE: node:18-slim
# Directories
CACHE_DIR: .caches
REPORT_DIR: .reports
......@@ -29,6 +29,7 @@ stages:
- checks
- analyse
- test
- cache
- packaging
- release
......@@ -107,7 +108,7 @@ lint-php:
- COMPOSER_MEMORY_LIMIT=-1
composer exec phplint
--
--json $PHPLINT_JSON_REPORT
--log-json=$PHPLINT_JSON_REPORT
--cache=$CACHE_LOCATION
after_script:
- ./.gitlab/scripts/convert-phplint-report $PHPLINT_JSON_REPORT > $PHPLINT_CODE_QUALITY_REPORT
......@@ -115,14 +116,14 @@ lint-php:
reports:
codequality: $PHPLINT_CODE_QUALITY_REPORT
lint-php-7.4:
image: studip/studip:tests-php8.2
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-7.4.json
PHPLINT_CODE_QUALITY_REPORT: $REPORT_DIR/phplint-codequality-7.4.json
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
......@@ -137,7 +138,7 @@ lint-php-7.4:
- COMPOSER_MEMORY_LIMIT=-1
composer exec phplint
--
--json $PHPLINT_JSON_REPORT
--log-json=$PHPLINT_JSON_REPORT
--cache=$CACHE_LOCATION
after_script:
- ./.gitlab/scripts/convert-phplint-report $PHPLINT_JSON_REPORT > $PHPLINT_CODE_QUALITY_REPORT
......@@ -159,17 +160,11 @@ lint-js:
interruptible: true
before_script:
- *mkdir-reports
- npm install -g npm@7
- npm install
--no-save --no-audit --no-fund
--loglevel=error
eslint eslint-formatter-gitlab
- npm ci --prefer--offline
script:
- npx eslint
--ext .js,.vue
- npm run lint-js --
--cache --cache-location $CACHE_LOCATION
--format gitlab
resources/assets/javascripts resources/vue
artifacts:
reports:
codequality: $ESLINT_CODE_QUALITY_REPORT
......@@ -183,24 +178,20 @@ lint-css:
STYLELINT_CODE_QUALITY_REPORT: $REPORT_DIR/stylelint-codequality.json
interruptible: true
cache:
- key: "$CI_JOB_NAME_SLUG:CI_COMMIT_REF_SLUG"
- key: "CI_COMMIT_REF_SLUG-lint-css"
paths:
- $CACHE_LOCATION
policy: pull-push
when: always
before_script:
- *mkdir-caches
- *mkdir-reports
- npm install
--no-save --no-audit --no-fund
--loglevel=error
stylelint@^14.9.1
stylelint-config-standard@^26.0.0
stylelint-formatter-gitlab
script:
- npx
stylelint
- npm run lint-css --
--cache --cache-location $CACHE_LOCATION
--custom-formatter=node_modules/stylelint-formatter-gitlab
--custom-formatter=node_modules/stylelint-formatter-gitlab
--output-file $STYLELINT_CODE_QUALITY_REPORT
resources/assets/stylesheets
artifacts:
reports:
codequality: $STYLELINT_CODE_QUALITY_REPORT
......@@ -211,9 +202,7 @@ phpstan:
variables:
CACHE_LOCATION: $CACHE_DIR/phpstan
PHPSTAN_CODE_QUALITY_REPORT: $REPORT_DIR/phpstan-codequality.json
allow_failure: true
interruptible: true
when: manual
cache:
- *composer-cache
- key: "$CO_JOB_NAME_SLUG:$CI_COMMIT_REF_SLUG"
......@@ -223,12 +212,12 @@ phpstan:
- *mkdir-caches
- *mkdir-reports
- *install-composer
- 'echo "includes:\n - phpstan.neon.dist\n\nparameters:\n tmpDir: $PHPSTAN_CACHE_PATH" > phpstan.neon'
- '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
composer/bin/phpstan analyse
--memory-limit=1G
--no-progress
--level=$PHPSTAN_LEVEL
--error-format=gitlab > $PHPSTAN_CODE_QUALITY_REPORT
after_script:
......@@ -414,11 +403,12 @@ packaging:
expire_in: never
build_image:
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:
......
# 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
#!/bin/bash
set -e
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
echo "INSTALL DB"
mysql -u $MYSQL_USER -h $MYSQL_HOST -p$MYSQL_PASSWORD $MYSQL_DATABASE < ./db/studip.sql
importSQLFile ./db/studip.sql
echo "INSTALL DEFAULT DATA"
mysql -u $MYSQL_USER -h $MYSQL_HOST -p$MYSQL_PASSWORD $MYSQL_DATABASE < ./db/studip_default_data.sql
mysql -u $MYSQL_USER -h $MYSQL_HOST -p$MYSQL_PASSWORD $MYSQL_DATABASE < ./db/studip_resources_default_data.sql
importSQLFile ./db/studip_default_data.sql
importSQLFile ./db/studip_resources_default_data.sql
echo "INSTALL ROOTUSER"
mysql -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
if [ ! -z $DEMO_DATA ]; then
echo "INSTALL DEMODATA"
mysql -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"
mysql -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"
mysql -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
echo "INSTALLATION FINISHED"
......
{
"extends": "stylelint-config-standard",
"extends": "stylelint-config-standard-scss",
"rules": {
"alpha-value-notation": null,
"at-rule-empty-line-before": 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-opening-brace-newline-after": null,
"block-opening-brace-space-after": null,
"block-opening-brace-space-before": null,
"color-function-notation": null,
"color-hex-case": null,
"color-hex-length": null,
"color-no-invalid-hex": null,
"comment-empty-line-before": null,
"comment-whitespace-inside": null,
"declaration-bang-space-after": null,
"declaration-bang-space-before": null,
"custom-property-empty-line-before": null,
"declaration-block-no-duplicate-properties": null,
"declaration-block-no-redundant-longhand-properties": 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-trailing-semicolon": null,
"declaration-colon-newline-after": null,
"declaration-colon-space-after": null,
"declaration-colon-space-before": null,
"declaration-empty-line-before": null,
"font-family-name-quotes": null,
"font-family-no-missing-generic-family-keyword": null,
"function-comma-space-after": null,
"function-comma-space-before": null,
"function-name-case": null,
"function-no-unknown": null,
"function-parentheses-newline-inside": null,
"function-parentheses-space-inside": null,
"function-url-quotes": null,
"hue-degree-notation": null,
"indentation": null,
"import-notation": "string",
"keyframes-name-pattern": null,
"length-zero-no-unit": null,
"max-empty-lines": null,
"max-line-length": null,
"media-feature-range-notation": "prefix",
"media-feature-name-no-vendor-prefix": null,
"no-descending-specificity": null,
"no-duplicate-selectors": null,
"no-empty-first-line": null,
"no-empty-source": null,
"no-eol-whitespace": null,
"no-extra-semicolons": null,
"no-invalid-position-at-import-rule": null,
"no-irregular-whitespace": null,
"no-missing-end-of-source-newline": null,
"number-leading-zero": null,
"number-max-precision": null,
"number-no-trailing-zeros": null,
"property-no-vendor-prefix": null,
"rule-empty-line-before": null,
"selector-attribute-quotes": 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-list-comma-newline-after": null,
"selector-no-vendor-prefix": null,
"selector-not-notation": null,
"selector-pseudo-element-colon-notation": null,
"shorthand-property-no-redundant-values": null,
"string-quotes": 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": [
"resource/assets/stylesheets/jquery-ui.structure.css",
"resources/assets/stylesheets/less/jquery-ui/*",
"resources/assets/stylesheets/vendor/*"
]
}
This diff is collapsed.
......@@ -38,7 +38,7 @@ PROJECT_NAME = Stud.IP
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = 5.4
PROJECT_NUMBER = 6.0
# 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
......
......@@ -87,12 +87,12 @@ optimize-icons: npm
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/" {} > {}' | 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/" {} > {}' | 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/" {} > {}' | 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/" {} > {}' | 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/" {} > {}' | 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/" {} > {}' | sed 's#icons/blue#icons/yellow#2' | sh
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
js-%.pot: $(VUE_SOURCES)
......
# Stud.IP v5.5
# Stud.IP v6.0
**23.05.23**
**15.03.2024**
## Neue Features
- Neben dem Vollbild-Modus (eingeführt in der Version 5.0), der nur in bestimmten Kontexten gezeigt wird, gibt es nun einen Modus "kompakte Navigation". Der neue Modus wird über das bisherige Icon für den Vollbildmodus aktiviert. Bitte passen Sie ihre Dokumentationen an.
### System
- Der Stud.IP-Cache ist nun kompatibel zu PSR-6. ([TIC #3701](https://gitlab.studip.de/studip/studip/-/issues/3701))
- Das `User`-Model hat die Methode `hasPermissionLevel()` erhalten, um einfach abfragen zu können, ob eine Person einen bestimmten Berechtigungsstatus hat. ([Issue #3453](https://gitlab.studip.de/studip/studip/-/issues/3453))
- In der Standort-Verwaltung können nun nicht nur Ferien sondern auch Feiertage konfiguriert werden. Dies erlaubt das Markieren von Feiertagen als gesetzliche Feiertage, da diese je nach Bundesland variieren können. ([Issue #2795](https://gitlab.studip.de/studip/studip/-/issues/2795))
- Die Nutzungsbedingungen sind nun nicht mehr als statische HTML-Dateien hinterlegt, sondern können analog zu Impressum, Datenschutz- und Barrierefreiheitserklärung direkt über die Oberfläche bearbeitet werden. Initial ist diese Seite aber im Entwurfsmodus und daher für Nicht-Roots unsichtbar. Damit andere Personen beim ersten Login diese Nutzungsbedingungen sehen und ihnen zustimmen können, muss der Entwurfsmodus für diese Seite abgeschaltet werden. ([TIC #4433](https://gitlab.studip.de/studip/studip/-/issues/4433))
### Layout
- Die Login-Seite wurde überarbeitet
- Das Design von Stud.IP wurde modernisiert
- Neue Avatarbilder
### Courseware
- Rechte und Sichtbarkeit überarbeitet
- Verbesserter Übersichtsdialog
- Rechte und Sichtbarkeit können für ein ganzes Lernmaterial gesetzt werden
- [Issue #3442](https://gitlab.studip.de/studip/studip/-/issues/3442)
- Peer-Review für Aufgaben
- Lehrende können Peer-Review-Prozess für Aufgaben einstellen
- Lernende sehen Aufgabenlösungen ein, geben Feedback und Bewertung dazu ab
- [Issue #2484](https://gitlab.studip.de/studip/studip/-/issues/2484)
- Blubber-Block
- Blubber Diskussionen können jetzt als Block eingebunden werden
- Lernmaterialübersicht im Inhaltsverzeichnis
- Schafft einen Überblick über weitere Lernmaterialien in der Veranstaltungen ohne den Kontext verlassen zu müssen
- Neues Layout für den Merksatz-Block
### Vips Plugin wird als Aufgaben-Werkzeug in Kern integriert
- Mit Vips lassen sich Selbsttests, Übungen und Klausuren erstellen
- Lernende können Vips Aufgabenblätter in Stud.IP bearbeiten und erhalten dort auch ihre Ergebnisse
- Für eine Vielzahl von Aufgabentypen besteht die Möglichkeit einer Autokorrektur
- [Issue #4258](https://gitlab.studip.de/studip/studip/-/issues/4258)
- [Plugin](https://develop.studip.de/studip/plugins.php/pluginmarket/presenting/details/81097da5ef66a002998b75d5eeece1f0)
### Neues Benachrichtigungssystem
- Vereinheitlichung wie Stud.IP mit Nutzenden kommuniziert
- Messageboxen, Companionmeldungen und Notifications werden vereinheitlicht
- [Issue #660](https://gitlab.studip.de/studip/studip/-/issues/660)
### Garuda Plugin in Kern integriert
- Mit Garuda können Zielgruppen definiert werden, um diesen Sammelnachrichten zukommen zu lassen
- [Issue #3326](https://gitlab.studip.de/studip/studip/-/issues/3326)
- [Plugin](https://develop.studip.de/studip/plugins.php/pluginmarket/presenting/details/d24cb47ee246033c325496b832e64147)
### Bilderpool
- Neuer Archiv Upload
- Ermöglicht das Einpflegen von einer Vielzahl von Bilder mit nur einem Upload
- Metadaten werden in dem Archiv als CSV-Datei mitgegeben und müssen nicht mehr einzeln eingegeben werden
- Stud.IP Bildersammlung kann mit nur einem Upload integriert werden
- Die Stud.IP Bildersammlung finden Sie [hier](https://gitlab.studip.de/studip/bilderpool)
### Anzeige von ILIAS-Kursen auf "Mein Arbeitsplatz"
- Bei aktivierter ILIAS-Schnittstelle können Lehrende ihre Stud.IP Veranstaltungen mit ILIAS-Kursen verknüpfen
- Lernende erhalten eine Übersicht über ihre ILIAS-Kurse im Stud.IP Arbeitsplatz
### Assistent für Roots nach Updates
- Nach einem Update auf eine neue Stud.IP Version werden Nutzenden mit Root-Rechten die neuen Features der Version präsentiert
### Studiengruppen
- Um Studiengruppen sichtbarer und interessanter zu machen wurde eine Reihe von Verbesserungen vorgenommen
- Neues Widget für die Startseite
- Möglichkeit Studiengruppen für eine Veranstaltungen vorzuschlagen
- [Issue #3616](https://gitlab.studip.de/studip/studip/-/issues/3616)
## Breaking changes
-
- Mindestanforderung an PHP auf 8.1 angehoben ([TIC #3805](https://gitlab.studip.de/studip/studip/issues/3805))
- Im Rahmen von [Issue #3788](https://gitlab.studip.de/studip/studip/-/issues/3788) wurden die Zusätze an allen Icons entfernt. Dadurch kann es sein, dass manche Plugins nicht mehr erscheinen. Diese müssen dann auf eine Variante ohne Zusätze umgestellt werden.
- Die Funktion `get_config()` wurde entfernt. Stattdessen muss die Methode `Config::get()->getValue('CONFIG_KEY')` bzw. der Shortcut `Config::get()->CONFIG_KEY` verwendet werden. ([Issue #2797](https://gitlab.studip.de/studip/studip/-/issues/2797))
- Die Funktion `smile()` wurde entfernt. Sie kann ersatzlos entfernt werden. ([Issue #3158](https://gitlab.studip.de/studip/studip/-/issues/3158))
- Die Funktion `transformBeforeSave()` wurde entfernt. Sie kann ersatzlos entfernt werden. ([Issue #3159](https://gitlab.studip.de/studip/studip/-/issues/3159))
- Die schon lange nicht mehr genutzten Methoden zum Setzen, Auslesen und Enfernen von Schmuckgrafiken von Bildern für die Sidebar wurde entfernt. Die Methoden `Sidebar::setImage()`, `Sidebar::getImage()` sowie `Sidebar::removeImage()` müssen ersatzlos entfernt werden. ([Issue #3157](https://gitlab.studip.de/studip/studip/-/issues/3157))
- Der zweite Parameter für die Methode `Navigation::setImage()` wurde entfernt. Der Parameter schien sich auf das Bild zu beziehen, hat aber Attribute an dem Link gesetzt. Stattdessen muss die Methode `Navigation::setLinkAttributes()` verwendet werden. ([Issue #3578](https://gitlab.studip.de/studip/studip/-/issues/3578))
- Die Unterstützung für LESS-Stylsheets in Plugins wurde entfernt. Als Alternative wird SCSS unterstützt. ([Issue #2720](https://gitlab.studip.de/studip/studip/-/issues/2720))
- Die Funktionen `studip_json_encode()` und `studip_json_decode()` wurden entfernt. Stattdessen müssen die Methode `json_encode()` und `json_decode()` verwendet werden. ([Issue #3814](https://gitlab.studip.de/studip/studip/-/issues/3814))
- Die `MembersModel.php` wurde entfernt ([Issue #3811](https://gitlab.studip.de/studip/studip/-/issues/3811))
- Die `admission.inc.php` wurde entfernt. ([Issue #3812](https://gitlab.studip.de/studip/studip/-/issues/3812))
- Die folgenden Funktionen wurden aus der Datei `lib/functions.php` entfernt: `re_sort_dozenten()`, `re_sort_tutoren()` und `get_next_position()` ([Issue #4002](https://gitlab.studip.de/studip/studip/-/issues/4002))
- Die Methoden `CronjobScheduler::scheduleOnce()` sowie `CronjobTask::scheduleOnce()` wurden ersatzlos entfernt. ([Issue #4078](https://gitlab.studip.de/studip/studip/-/issues/4078))
- Die folgenden Klassen wurden innerhalb von Stud.IP verschoben. Da sie über den Autoloader geladen werden, kann jedes manuelle Einbinden ersatzlos entfernt werden. ([Issue #4105](https://gitlab.studip.de/studip/studip/-/issues/4105))
- `AuthenticatedController`
- `PluginController`
- `StudipController`
- `StudipControllerPropertiesTrait`
- `StudipResponse`
- Im Rahmen von [Issue #4118](https://gitlab.studip.de/studip/studip/-/issues/4118) wurde `write_excel` ausgebaut. Als Alternative kann `phpoffice/phpspreadsheet` verwendet werden.
- Im Rahmen von [TIC #3701](https://gitlab.studip.de/studip/studip/-/issues/3701) wurden die Klassen für den Cache umbenannt. Alle Vorkommnisse sollten ersetzt werden:
- `StudipCacheFactory` -> `Studip\Cache\Factory`
- Die Bibliothek `opis/json-schema` wurde auf Version 2.3.0 aktualisiert ([Issue #4173](https://gitlab.studip.de/studip/studip/-/issues/4173)). Dadurch ergeben sich die folgenden Änderungen für Komponenten aus Courseware (siehe auch [Migration Guide](https://opis.io/json-schema/2.x/php-migration.html#validator)):
- Instanzen von `Courseware\ContainerTypes\BlockType` müssen die Methode `getJsonSchema` anpassen. Der Return Type ist nun `string` und es muss der Inhalt der Schema-Datei zurückgegeben werden ohne Aufruf von `Schema::fromJsonString()`.
- Instanzen von `Courseware\ContainerTypes\ContainerType` müssen die Methode `getJsonSchema` anpassen. Der Return Type ist nun `string` und es muss der Inhalt der Schema-Datei zurückgegeben werden ohne Aufruf von `Schema::fromJsonString()`.
- Die von Stud.IP verwendete Template-Bibliothek "Flexi Templates" wurde vollständig in den Kern integriert.
Obwohl die Umstellung abwärtskompatibel sein sollte, sollten die Klassen folgendermassen ersetzt werden:
- `Flexi_TemplateFactory` > `Flexi\Factory`
- `Flexi_Template` > `Flexi\Template`
- `Flexi_PhpTemplate` > `Flexi\PhpTemplate`
- `Flexi_TemplateNotFoundException` > `Flexi\TemplateNotFoundException`
Sollte ein Plugin manuell Flexi einbinden, so wird dies zu einem Fehler führen. Jegliches Einbinden von Dateien
unterhalb von `vendor/flexi` muss ersatzlos entfernt werden.
- Die folgenden Funktionen wurden entfernt ([Issue #4179](https://gitlab.studip.de/studip/studip/-/issues/4179))
- `getWeekdays($short = true)`
- `veranstaltung_beginn($seminar_id = '', $return_mode = '')`
- `veranstaltung_beginn_from_metadata($reg_irreg, $sem_begin, $start_woche, $start_termin,$turnus_data, $return_mode='int')`
- `get_sem_name ($time)`
- `get_sem_num ($time)`
- `get_sem_num_sem_browse ()`
- `get_semester($seminar_id)`
- `delete_date($termin_id, $topic_delete = TRUE, $folder_move = TRUE, $sem_id=0)`
- `delete_range_of_dates($range_id, $topics = FALSE)`
- `isSchedule ($sem_id, $presence_dates_only = TRUE, $clearcache = FALSE)`
- `isMetadateCorrespondingDate ($termin_id, $begin = '', $end = '', $seminar_id='')`
- `getPresenceTypes()`
- Die Klasse `AuxLockRules` wurde ausgebaut. ([Issue #4187](https://gitlab.studip.de/studip/studip/-/issues/4187))
- Die Klasse `ProfileModel` wurde gelöscht. Die darin enthaltenen Methoden wurden in den `Profile_Controller` verschoben. ([Issue #4185]https://gitlab.studip.de/studip/studip/-/issues/4185))
- Die Klasse `StudipTransformFormat` wurde ausgebaut ([Issue #4188](https://gitlab.studip.de/studip/studip/-/issues/4188))
- Die REST-API (`public/api.php`) wurde zu Stud.IP 5.0 deprecated und nun mit Stud.IP 6.0 entfernt. Als Ersatz steht die JSONAPI zur Verfügung. ([Issue #2798](https://gitlab.studip.de/studip/studip/-/issues/2798))
- Die Klassen `CalendarView`, `CalendarScheduleModel` sowie alle davon abhängigen Klassen wurden entfernt. ([Issue #4421](https://gitlab.studip.de/studip/studip/-/issues/4421))
- Anstelle von `CalendarView` sollte `\Studip\Fullcalendar` verwendet werden.
- Das Datenbankschema des Stundenplans wurde geändert. ([Issue #4421](https://gitlab.studip.de/studip/studip/-/issues/4421))
- Die Evaluationen wurden ausgebaut. Stattdessen sollte man nun die neuen Fragebögen verwenden ([Issue #3787]https://gitlab.studip.de/studip/studip/-/issues/3787)
- Die Klassen `DbView`, `DbSnapshot` und die zugehörigen Dateien in `lib/dbviews` wurden ausgebaut. ([Issue #4390](https://gitlab.studip.de/studip/studip/-/issues/4390))
- Als Ersatz dienen Datenbankabfragen mittels der `DBManager`-Klasse oder mittels `SimpleORMap`-Modellen.
- Es wurden zwei neue CLI-Kommandos hinzugefügt, womit man Klassenrümpfe für SORM-Models und Migrationen erstellen kann. Bei den Migrationen wird die Versionsnummer für die jeweilige `domain` automatisch ermittelt.
- `cli/studip make:model` und `cli/studip make:migration`.
- Es wurde ein neues CLI-Kommando hinzugefügt, womit man auf einfache Weise ein Plugin-Grundgerüst erstellen kann.
- `cli/studip make:plugin`
- Die Klasse `Seminar`, sowie die Klassen in `lib/raumzeit` wurden ausgebaut. ([Issue #3209](https://gitlab.studip.de/studip/studip/-/issues/3209))
- Als Ersatz für viele Methoden der Seminar-Klasse dienen die Klassen `Course`, `CourseDate` und `SeminarCycleDate`, sowie die neue `CourseDateList`-Klasse.
- Die Klassen `TreeAbstract`, `TreeView` und `SemBrowse` wurden ausgebaut. ([Issue #4392](https://gitlab.studip.de/studip/studip/-/issues/4392))
- Zur Anzeige von Baumstrukturen können als Ersatz die Implementierungen des `StudipTreeNode`-Interfaces genutzt werden.
- Die Zuordnung von Veranstaltungen zu Semestern anhand von Timestamps wurde entfernt. In der Datenbank wurden die Spalten `start_time` und `duration_time` der Tabelle `seminare` entfernt. ([Issue #4391]https://gitlab.studip.de/studip/studip/-/issues/4391))
- Plugins, die Veranstaltungen anhand von Timestamps laden oder anderweitig verwenden, müssen angepasst werden!
- Das Mapping von Veranstaltungen zu Semestern findet nun ausschließlich anhand der Semester-ID über die Verknüpfungstabelle `semester_courses` statt.
- Die ELearning-Schnittstelle wurde ausgebaut. In diesem Rahmen wurden auch die Methoden `printhead()` und `printcontent()` ersatzlos entfernt. ([Issue #4109](https://gitlab.studip.de/studip/studip/-/issues/4109))
## Security related issues
......@@ -16,8 +150,8 @@
## Deprecated Features
- Das Verwenden von LESS-Stylesheets in Plugins wurde deprecated und wird zu Stud.IP 6.0 entfernt werden. Die betroffenen Plugins müssen angepasst und auf SCSS umgestellt werden.
-
## Known Issues
- Der Vollbildmodus funktioniert nicht auf Apple iPads. Der Modus kann zwar initiiert werden, beendet sich aber selbsständig, wenn nach oben gescrollt wird. Dieses Verhalten ist en Fehler innerhalb von iOS/iPadOS und kann seitens Stud.IP nicht umgangen werden. Der Fehler ist bei Apple gemeldet.
-
RELEASE 5.4.alpha
RELEASE 6.0.alpha
......@@ -3,6 +3,21 @@ 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'));
......@@ -131,6 +146,9 @@ class Accessibility_FormsController extends StudipController
}
$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());
......
......@@ -53,7 +53,7 @@ class ActivityfeedController extends AuthenticatedController
unset($modules[Context::INSTITUTE]['participants']);
unset($modules[Context::INSTITUTE]['schedule']);
$standard_plugins = PluginManager::getInstance()->getPlugins("StandardPlugin");
$standard_plugins = PluginManager::getInstance()->getPlugins(StandardPlugin::class);
foreach ($standard_plugins as $plugin) {
if ($plugin instanceof ActivityProvider) {
$modules[Context::COURSE][$plugin->getPluginName()] = $plugin->getPluginName();
......@@ -67,7 +67,7 @@ class ActivityfeedController extends AuthenticatedController
'blubber' => _('Blubber'),
];
$homepage_plugins = PluginEngine::getPlugins('HomepagePlugin');
$homepage_plugins = PluginEngine::getPlugins(HomepagePlugin::class);
foreach ($homepage_plugins as $plugin) {
if ($plugin->isActivated($GLOBALS['user']->id, 'user')) {
if ($plugin instanceof ActivityProvider) {
......@@ -92,4 +92,193 @@ class ActivityfeedController extends AuthenticatedController
PageLayout::setTitle(_('Aktivitäten konfigurieren'));
}
public function load_action(): void
{
$user = User::findCurrent();
// failsafe einbauen - falls es keine älteren Aktivitäten mehr im System gibt, Abbruch!
$oldest_activity = \Studip\Activity\Activity::getOldestActivity();
$max_age = $oldest_activity ? $oldest_activity->mkdate : time();
$contexts = [];
// create system context
$system_context = new \Studip\Activity\SystemContext($user);
$contexts[] = $system_context;
$contexts[] = new \Studip\Activity\UserContext($user, $user);
$user->contacts->each(function ($another_user) use (&$contexts, $user) {
$contexts[] = new \Studip\Activity\UserContext($another_user, $user);
});
if (!in_array($user->perms, ['admin','root'])) {
// create courses and institutes context
foreach (\Course::findMany($user->course_memberships->pluck('seminar_id')) as $course) {
$contexts[] = new \Studip\Activity\CourseContext($course, $user);
}
foreach (\Institute::findMany($user->institute_memberships->pluck('institut_id')) as $institute) {
$contexts[] = new \Studip\Activity\InstituteContext($institute, $user);
}
}
// add filters
$filter = new \Studip\Activity\Filter();
$start = Request::int('start', strtotime('yesterday'));
$end = Request::int('end', time());
$scrollfrom = Request::int('scrollfrom', false);
$filtertype = Request::get('filtertype', '');
$objectType = Request::get('object_type');
$filter->setObjectType($objectType);
$objectId = Request::get('object_id');
$filter->setObjectId($objectId);
$context = Request::get('context_type');
$filter->setContext($context);
$contextId = Request::get('context_id');
$filter->setContextId($contextId);
if (!empty($filtertype)) {
$filter->setType(json_decode($filtertype));
}
if ($scrollfrom) {
// shorten "watch-window" by one second to prevent duplication of activities
$scrollfrom -= 1;
if ($scrollfrom > $max_age){
$end = $scrollfrom;
$start = strtotime('yesterday', $end);
$data = [];
$backtrack = 1;
while (empty($data)) {
$filter->setStartDate($start);
$filter->setEndDate($end);
$data = $this->getStreamData($contexts, $filter);
if ($start < $max_age) {
break;
}
// move "watch-window" back one day at a time
$end = $start - 1;
$start = strtotime("-{$backtrack} days", $start);
// enforce maximum "watch-window", currently 2 weeks
$backtrack = min(14, $backtrack + 1);
}
} else {
$data = false;
}
} else {
$filter->setStartDate($start);
$filter->setEndDate($end);
$data = $this->getStreamData($contexts, $filter);
}
// set etag for preventing resending the same stuff over and over again
$etag = md5(serialize($data));
$this->response->add_header('ETag', '"' . $etag . '"');
if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $this->etagMatches($etag, $_SERVER['HTTP_IF_NONE_MATCH'])) {
$this->set_status(304);
$this->render_nothing();
return;
}
if (isset($_SERVER['HTTP_IF_MATCH']) && !$this->etagMatches($etag, $_SERVER['HTTP_IF_MATCH'])) {
$this->set_status(412);
$this->render_nothing();
return;
}
$this->render_json($data);
}
/**
* private helper function to get stream data for given contexts and filter
*
* @param $contexts
* @param $filter
* @return array
*/
private function getStreamData($contexts, $filter): array
{
$stream = new Studip\Activity\Stream($contexts, $filter);
$data = $stream->toArray();
foreach ($data as $key => $act) {
$actor = [
'type' => $act['actor_type'],
'id' => $act['actor_id'],
];
if ($act['actor_type'] == 'user') {
$a_user = \User::findFull($act['actor_id']);
$actor['details'] = $this->getMiniUser($a_user ?: new \User());
} elseif ($act['actor_type'] === 'anonymous') {
$actor['details'] = [
'name' => _('Anonym'),
];
}
unset($data[$key]['actor_type']);
unset($data[$key]['actor_id']);
$data[$key]['actor'] = $actor;
}
return $data;
}
private function getMiniUser(User $user): array
{
$avatar = \Avatar::getAvatar($user->id);
return [
'id' => $user->id,
'name' => $this->getNamesOfUser($user),
'avatar_small' => $avatar->getURL(\Avatar::SMALL),
'avatar_medium' => $avatar->getURL(\Avatar::MEDIUM),
'avatar_normal' => $avatar->getURL(\Avatar::NORMAL),
'avatar_original' => $avatar->getURL(\Avatar::NORMAL)
];
}
private function getNamesOfUser(User $user): array
{
return [
'username' => $user->username,
'formatted' => $user->getFullName(),
'family' => $user->nachname,
'given' => $user->vorname,
'prefix' => $user->title_front,
'suffix' => $user->title_rear,
];
}
// Helper method checking if a ETag value list includes the current ETag.
private function etagMatches(string $etag, string $list)
{
if ($list === '*') {
return true;
}
return in_array(
$etag,
preg_split('/\s*,\s*/', $list)
);
}
}
......@@ -30,6 +30,10 @@ class Admin_AdditionalController extends AuthenticatedController
throw new AccessDeniedException(_("Sie haben keine Berechtigung diese " .
"Veranstaltung zu verändern."));
}
if ($GLOBALS['perm']->have_studip_perm('admin', $this->course->id)) {
Sidebar::get()->addWidget(new CourseManagementSelectWidget());
}
}
/**
......
<?php
/**
*
**/
class Admin_ApiController extends AuthenticatedController
{
/**
*
**/
public function before_filter(&$action, &$args)
{
parent::before_filter($action, $args);
require_once 'lib/bootstrap-api.php';
$GLOBALS['perm']->check('root');
Navigation::activateItem('/admin/config/api');
PageLayout::setTitle(_('API Verwaltung'));
$this->types = [
'website' => _('Website'),
'desktop' => _('Herkömmliches Desktopprogramm'),
'mobile' => _('Mobile App')
];
// Sidebar
$views = new ViewsWidget();
$views->addLink(_('Registrierte Applikationen'),
$this->url_for('admin/api'))
->setActive($action === 'index');
$views->addLink(_('Globale Zugriffseinstellungen'),
$this->url_for('admin/api/permissions'))
->setActive($action == 'permissions');
$views->addLink(_('Konfiguration'),
$this->url_for('admin/api/config'))
->setActive($action == 'config');
Sidebar::get()->addWidget($views);
$actions = new ActionsWidget();
$actions->addLink(_('Neue Applikation registrieren'),
$this->url_for('admin/api/edit'),
Icon::create('add', 'clickable'))
->asDialog();
Sidebar::get()->addWidget($actions);
}
/**
*
**/
public function index_action()
{
$this->consumers = RESTAPI\Consumer\Base::findAll();
$this->routes = RESTAPI\Router::getInstance()->getRoutes(true);
}
/**
*
**/
public function render_keys($id)
{
$consumer = RESTAPI\Consumer\Base::find($id);
return [
'Consumer Key = ' . $consumer->auth_key,
'Consumer Secret = ' . $consumer->auth_secret,
];
}
/**
*
**/
public function keys_action($id)
{
$details = $this->render_keys($id);
if (Request::isXhr()) {
$this->render_text(implode('<br>', $details));
} else {
PageLayout::postMessage(MessageBox::info(_('Die Schlüssel in den Details dieser Meldung sollten vertraulich behandelt werden!'), $details, true));
$this->redirect('admin/api/#' . $id);
}
}
/**
*
**/
public function edit_action($id = null)
{
$consumer = $id
? RESTAPI\Consumer\Base::find($id)
: RESTAPI\Consumer\Base::create(Request::option('consumer_type') ?: 'oauth');
if (Request::submitted('store')) {
$errors = [];
$consumer->active = (bool) Request::int('active');
$consumer->title = Request::get('title');
$consumer->contact = Request::get('contact');
$consumer->email = Request::get('email');
$consumer->callback = Request::get('callback');
$consumer->url = Request::get('url');
$consumer->type = Request::get('type') ?: null;
$consumer->commercial = Request::int('commercial');
$consumer->notes = Request::get('notes');
$consumer->description = Request::get('description');
if (!empty($errors)) {
$message = MessageBox::error(_('Folgende Fehler sind aufgetreten:'), $errors);
PageLayout::postMessage($message);
return;
}
$consumer->store();
if ($id) {
$message = MessageBox::success(_('Die Applikation wurde erfolgreich gespeichert.'));
} else {
$details = $this->render_keys($consumer->id);
$message = MessageBox::success(_('Die Applikation wurde erfolgreich erstellt, die Schlüssel finden Sie in den Details dieser Meldung.'), $details, true);
}
PageLayout::postMessage($message);
$this->redirect('admin/api/index#' . $consumer->id);
return;
}
$this->consumer = $consumer;
$this->id = $id;
}
/**
*
**/
public function toggle_action($id, $state = null)
{
$consumer = RESTAPI\Consumer\Base::find($id);
$consumer->active = $state === null ? !$consumer->active : ($state === 'on');
$consumer->store();
$message = $state
? _('Die Applikation wurde erfolgreich aktiviert.')
: _('Die Applikation wurde erfolgreich deaktiviert.');
PageLayout::postMessage(MessageBox::success($message));
$this->redirect('admin/api/#' . $consumer->id);
}
/**
*
**/
public function delete_action($id)
{
if (!Request::isPost()) {
throw new MethodNotAllowedException();
}
if ($consumer = RESTAPI\Consumer\Base::find($id)) {
$consumer->delete();
PageLayout::postSuccess(_('Die Applikation wurde erfolgreich gelöscht.'));
}
$this->redirect('admin/api');
}
/**
*
**/
public function permissions_action($consumer_id = null)
{
if (Request::submitted('store')) {
$perms = Request::getArray('permission');
$permissions = RESTAPI\ConsumerPermissions::get($consumer_id ?: 'global');
foreach ($perms as $route => $methods) {
foreach ($methods as $method => $granted) {
$permissions->set(urldecode($route), urldecode($method), (bool)$granted, true);
}
}
$permissions->store();
PageLayout::postMessage(MessageBox::success(_('Die Zugriffsberechtigungen wurden erfolgreich gespeichert')));
$this->redirect($consumer_id ? 'admin/api' : 'admin/api/permissions');
return;
}
$title = $consumer_id ? _('Zugriffsberechtigungen') : _('Globale Zugriffsberechtigungen');
$title .= ' - ' . PageLayout::getTitle();
PageLayout::setTitle($title);
$this->consumer_id = $consumer_id;
$this->router = RESTAPI\Router::getInstance();
$this->routes = $this->router->getRoutes(true, false);
$this->permissions = RESTAPI\ConsumerPermissions::get($consumer_id ?: 'global');
$this->global = $consumer_id ? RESTAPI\ConsumerPermissions::get('global') : false;
}
public function config_action()
{
$this->config = Config::get();
if (Request::isPost()) {
$this->config->store('API_ENABLED', Request::int('active', 0));
$this->config->store('API_OAUTH_AUTH_PLUGIN', Request::option('auth'));
PageLayout::postMessage(MessageBox::success(_('Die Einstellungen wurden gespeichert.')));
$this->redirect('admin/api/config');
}
}
}
......@@ -44,11 +44,11 @@ class Admin_AutoinsertController extends AuthenticatedController
if (Request::submitted('suchen')) {
if (Request::get('sem_search')) {
$this->sem_search = Request::get('sem_search');
$this->sem_select = Request::option('sem_select');
$this->sem_select = Request::option('sem_select') ?: null;
$search = new SeminarSearch();
$this->seminar_search = $search->getResults
(Request::get('sem_search'),
['search_sem_sem' => Request::option('sem_select')]
$this->seminar_search = $search->getResults(
$this->sem_search,
['search_sem_sem' => $this->sem_select]
);
if (count($this->seminar_search) == 0) {
PageLayout::postInfo(_('Es wurden keine Veranstaltungen gefunden.'));
......@@ -159,7 +159,7 @@ class Admin_AutoinsertController extends AuthenticatedController
} elseif (!count($filters)) {
PageLayout::postError(_('Keine Filterkriterien gewählt'));
} else {
$seminar = Seminar::GetInstance($seminar_id);
$course = Course::find($seminar_id);
$userlookup = new UserLookup();
foreach ($filters as $type => $values) {
......@@ -170,8 +170,11 @@ class Admin_AutoinsertController extends AuthenticatedController
foreach ($user_ids as $user_id) {
if ($force || !AutoInsert::checkAutoInsertUser($seminar_id, $user_id)) {
$real_users += $seminar->addMember($user_id) ? 1 : 0;
AutoInsert::saveAutoInsertUser($seminar_id, $user_id);
$user = User::find($user_id);
if ($user) {
$real_users += $course->addMember($user) ? 1 : 0;
AutoInsert::saveAutoInsertUser($seminar_id, $user_id);
}
}
}
......@@ -182,9 +185,8 @@ class Admin_AutoinsertController extends AuthenticatedController
count($user_ids),
sprintf(
'<a href="%s">%s</a>',
URLHelper::getLink('dispatch.php/course/details/', ['cid' => $seminar->getId()]),
htmlReady($seminar->getName()
)
URLHelper::getLink('dispatch.php/course/details/', ['cid' => $course->id]),
htmlReady($course->name)
)
);
$details = [_('Etwaige Abweichungen der Personenzahlen enstehen durch bereits vorhandene bzw. wieder ausgetragene Personen.')];
......
......@@ -156,9 +156,7 @@ class Admin_BannerController extends AuthenticatedController
}
break;
case 'seminar':
try {
Seminar::getInstance($target);
} catch (Exception $e) {
if (!Course::exists($target)) {
$errors[] = _('Die angegebene Veranstaltung existiert nicht. '
.'Bitte geben Sie eine gültige Veranstaltungs-ID ein.');
}
......@@ -199,14 +197,14 @@ class Admin_BannerController extends AuthenticatedController
->defaultValue($banner->target,$seminar_name['name'])
->render();
}
if ($banner->target_type == 'user') {
$this->user = QuickSearch::get('user', new StandardSearch('username'))
->setInputStyle('width: 240px')
->defaultValue($banner->target, $banner->target)
->render();
}
if ($banner->target_type == 'inst') {
$institut_name = get_object_name($banner->target, 'inst');
$this->institut = QuickSearch::get('institut', new StandardSearch('Institut_id'))
......
......@@ -47,16 +47,14 @@ class Admin_CacheController extends AuthenticatedController
$this->sidebar->addWidget($views);
if ($this->enabled) {
$actions = new ActionsWidget();
$actions->addLink(
_('Cache leeren'),
$this->url_for('admin/cache/flush'),
Icon::create('decline'),
['data-confirm' => _('Soll der gesamte Inhalt des Caches wirklich gelöscht werden?')]
);
$this->sidebar->addWidget($actions);
}
$actions = new ActionsWidget();
$actions->addLink(
_('Cache leeren'),
$this->url_for('admin/cache/flush'),
Icon::create('decline'),
['data-confirm' => _('Soll der gesamte Inhalt des Caches wirklich gelöscht werden?')]
);
$this->sidebar->addWidget($actions);
}
/**
......@@ -64,28 +62,29 @@ class Admin_CacheController extends AuthenticatedController
*/
public function settings_action()
{
if ($this->enabled) {
$this->types = CacheType::findAndMapBySQL(function (CacheType $type) {
return $type->toArray();
}, "1 ORDER BY `cache_id`");
$currentCache = Config::get()->SYSTEMCACHE;
$currentCacheClass = CacheType::findOneByClass_name($currentCache['type']);
$this->cache = $currentCacheClass->class_name;
$this->config = $currentCacheClass->class_name::getConfig();
} else {
PageLayout::postWarning(
_('Caching ist systemweit ausgeschaltet, daher kann hier nichts konfiguriert werden.'));
}
$currentCache = Config::get()->SYSTEMCACHE;
$currentCacheClass = CacheType::findOneByClass_name($currentCache['type']);
$this->render_vue_app(
Studip\VueApp::create('CacheAdministration')
->withProps([
'enabled' => (bool) $this->enabled,
'currentCache' => $currentCacheClass->class_name,
'currentConfig' => $currentCacheClass->class_name::getConfig(),
'cacheTypes' => CacheType::findAndMapBySQL(
fn(CacheType $type) => $type->toArray(),
"1 ORDER BY `cache_id`"
),
])
);
}
/**
* Fetches necessary configuration for given cache type.
*
* @param string $className
*/
public function get_config_action($className)
public function get_config_action()
{
$className = Request::get('cache');
$type = CacheType::findOneByClass_name($className);
$this->render_json($type->class_name::getConfig());
......@@ -111,7 +110,7 @@ class Admin_CacheController extends AuthenticatedController
// Store settings to global config.
if (Config::get()->store('SYSTEMCACHE', $settings)) {
PageLayout::postSuccess(_('Die Einstellungen wurden gespeichert.'));
StudipCacheFactory::unconfigure();
\Studip\Cache\Factory::unconfigure();
}
$this->relocate('admin/cache/settings');
......@@ -122,7 +121,7 @@ class Admin_CacheController extends AuthenticatedController
*/
public function flush_action()
{
$cache = StudipCacheFactory::getCache();
$cache = \Studip\Cache\Factory::loadSystemCache(true);
$cache->flush();
PageLayout::postSuccess(_('Die Inhalte des Caches wurden gelöscht.'));
......@@ -135,7 +134,7 @@ class Admin_CacheController extends AuthenticatedController
*/
public function stats_action()
{
$cache = StudipCacheFactory::getCache();
$cache = \Studip\Cache\Factory::getCache();
$this->stats = $cache->getStats();
}
......