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 (183)
Showing
with 397 additions and 103 deletions
18.11.2022 v 5.1.1
https://gitlab.studip.de/studip/studip/-/issues?milestone_title=Stud.IP+5.1.1&state=all
- Courseware PDF-Export: Block Infomationen im Fallback nicht immer brauchbar [#723]
- Verwendung von `have_studip_perm()` in lib/classes/JsonApi/Routes/Courseware/Authority.php [#1047]
- Courseware: Aufgaben zuweisen [#1122]
- OER-Campus > Entdeckermodus > Schlagwortbox [#1129]
- Courseware: Bearbeiten/Verwalten von zugewiesenen Aufgaben [#1144]
- Courseware: Hängt bei "Lege Import Ordner an" [#1259]
- Courseware Bookmark Übersicht ist leer [#1406]
- Bearbeiten als Teilnehmende auch mit eingestellter Berechtigung nicht möglich [#1452]
- Fehler beim Hinzufügen von JSONAPI-Routen durch Plugins [#1505]
- StudipController::url_for('', ['foo' => 'bar']) ignoriert die übergebenen Parameter [#1538]
- Aktivitätsfeed ist kaputt [#1557]
- Signatur der Methoden zum Hinzufügen von Routen an JsonApi\Contracts\JsonApiPlugin sind fehlerhaft [#1567]
- Arbeitsplatz / Courseware : Art des Lernmaterials wird beim Erstellen nicht gesetzt [#1584]
- Courseware Art des Lernmaterials inkonsistent benannt [#1585]
- Fehler in Sprechstunden beim Zusammenführen von Accounts [#1625]
- Sequentielle Reihenfolge: Nicht zur Verfügung stehende Kapitel können über die Exportfunktion weiterhin eingesehen werden [#1632]
- Terminvergabe: Bulkaktionen in der Verwaltung der Termine funktionieren nicht wie erwartet [#1641]
- Passwortlink beim Zurücksetzen über die Adminoberfläche ist nicht lang genug gültig [#1647]
- Errorhandler für die JSONAPI sollten auch den richtigen Content-Type setzen [#1659]
18.11.2022 v 5.0.3
https://gitlab.studip.de/studip/studip/-/issues?milestone_title=Stud.IP+5.0.3&state=all
- Benachrichtigungen sind nicht per Tastaturnavigation erreichbar [#109]
- Fehlender Uni-Name bei Mail zur Passwortänderung [#134]
- Infodialog zu Ressourcen ignoriert Einstellung RESOURCES_SHOW_PUBLIC_ROOM_PLANS [#143]
- "Wiki-Seiten importeren" findet keine Veranstaltungen mehr [#145]
- Raumplanung: Sortierung der Raumanfragen funktioniert nicht [#188]
- Raumanfragen: Suche anhand der gewünschten Raumeigenschaften findet zu wenig Räume [#239]
- Raumanfragen: Teilweise belegte Räume nicht buchbar [#240]
- Migration der Seminare-Semester-Tabelle ist fehlerhaft [#249]
- Seite "Raumverwaltung > Übersicht > Räume" lädt sehr langsam [#357]
- Hierarchie beim Anlegen von Räumen ist falsch sortiert [#358]
- Neu angelegte Accounts bekommen kein Paßwort und können auch keines setzen [#513]
- Teilnehmendenseite: „Nachricht mit Mailweiterleitung senden“ wird doppelt vorgelesen [#562]
- Dateibereich: Aktion „Bildergalerie öffnen“ tut nichts [#620]
- Courseware: Kopieren von Inhalten in den gleichen Kurs nicht möglich [#636]
- Fehlender globaler Schalter für das Abschalten der Courseware (veranstaltungsunabhängig) [#648]
- Austragen einer Person aus einer VA aktualisiert consultation_events nicht [#675]
- "Passwortlink zusenden" funktioniert für Admins und Root nicht [#866]
- Courseware: Unterstützung von Hausaufgabenordnern [#874]
- Courseware: Teile des Inhaltsverzeichnis nicht durch Scrollen zu erreichen [#900]
- Courseware: "Lesezeichen setzen" setzt kein Lesezeichen und wirft Fehler [#910]
- Courseware: Import von Inhalten zeigt keine Dateien an, wenn Lizenz keinen Download erlaubt [#921]
- Springende Navigationsbar im Vollbildmodus [#967]
- Gelöschter/abgesagter Termin verbleibt im Terminkalender [#982]
- Courseware: TypeError: n['users/byId'](...) is undefined [#994]
- Courseware: Lernkarte wird beim Laden des Blocks nicht korrekt aktiviert [#996]
- Youtube-Video im Embed-Block wird nicht korrekt formatiert, wenn es in einem Tab-Abschnitt liegt [#1002]
- Courseware: Block Audioaufnahme: Audioaufnahme lässt sich nicht speichern. [#1058]
- Hinzufügen einer Einrichtung zu Personen funktioniert nicht, wenn die Berechtigungsstufe der Person durch ein Authentifizerungsplugin gesperrt wurde [#1096]
- Konversationssuche im Veranstaltungsblubber funktioniert nicht [#1116]
- Stud.IP 5.1: Fehlermeldung bei der Aktivierung des DB-Caches [#1124]
- Fehler beim Import von Ordnern ohne Namen (ggf. ist der Export schon defekt?) [#1160]
- Webpack 5.6 ist nicht mit OpenSSL 3 kompatibel [#1216]
- Courseware: "TypeError: t.container is undefined" in der Console [#1285]
- Courseware: Fehler bei Farbauswahl im Leinwand-Block [#1291]
- Courseware: Fehler beim Löschen eines Blocks [#1292]
- Verhaltensänderung in RolePersistence::getAssignedRoleInstitutes() durch #1180 [#1360]
- Courseware: Abschnitte und Seiten sind nach dem Kopieren in falscher Reihenfolge [#1361]
- OER-Campus: Kontrastschwache Texte [#1365]
- Login: Kontrast zu schwach [#1367]
- jQuery Datumswähler: Kontraste nicht optimal [#1372]
- Profil: Graue Schrift [#1373]
- Footer: Hover ändern [#1379]
- Hilfelasche: Unnötiger Hovereffekt [#1380]
- Blubber: An mehreren Stellen wird grauer und kontrastschwacher Text verwendet [#1383]
- OER-Campus: Titel werden je nach Browser anders/ungünstig gekürzt [#1385]
- Beim Hochladen einer Datei sind unter Chromium / Chrome nicht alle Nutzungsbedingungen per Tastatur auswählbar [#1390]
- Courseware: Übersetzung der Blocktypen und -beschreibungen funktioniert nicht [#1394]
- Admins können Veranstaltungen keinen Hauptveranstaltungen zuweisen [#1449]
- Courseware: Fortschrittsanzeige bleibt immer bei 0% [#1453]
- Courseware enthält unsichtbare Blöcke, die aber beim Fortschritt mitgezählt werden [#1454]
- Kleiner Schreibfehler bei Passwortänderungsmail [#1492]
- Erkennung vom High Contrast Mode ist unter Umständen kaputt [#1493]
- "Neue" Icons auf der Seite "Meine Veranstaltungen" im High Contrast-Modus werden grau [#1500]
- Voreingestellte Plugins für Einrichtungen sind nach dem Update auf 5.0 nicht mehr aktiviert [#1506]
- Anlegeassistent speichert Semesterzuordnung nicht [#1507]
- Hilfelasche: redundantes CSS beim Hovereffekt [#1533]
- Cacheverwaltung: Platzhalter in den Einstellungen sind etwas verwirrend [#1536]
- Fehler bei "Meine Studiengruppen" Übersicht mit neuen Dateien [#1541]
- PHP Warning: Division by zero [#1542]
- $this->user gibt es nicht (Folgeproblem von #836) [#1545]
- PHP Warning: count(): Parameter must be an array or an object that implements Countable in lib/classes/coursewizardsteps/LVGroupsWizardStep.php on line 409 [#1550]
- Courseware: Fehler beim Laden, wenn man Admin oder nur Vertretung im Kurs ist [#1551]
- Schlechte Performance von Suche in GlobalSearchCourses [#1561]
- Fehler bei der Terminvereinbarung - Sidebar [#1564]
- Hinweis auf noch auszufügende Migrationen erscheint nach 5 Minuten wieder [#1566]
- JSONAPI erlaubt das Setzen der Sprache über HTTP-Header "Accept-Language" nicht [#1568]
- Courseware lädt nicht mehr : 500 Class 'JsonApi\PluginManager' not found [#1570]
- Courseware: Funktion "Elemente hinzufügen" ist unten abgeschnitten [#1571]
- Courseware: Falsches HTML-Escaping im Dialog zum Export [#1575]
- Falsche E-Mail beim Setzen eines Paßworts [#1590]
- Übersetzungen mehrsprachiger Config-Einstellungen bleiben nach dem Löschen in der DB zurück [#1597]
- MyCoursesSearch liefert bei aktiviertem DEPUTIES_ENABLE falsche Ergebnisse [#1606]
- Tab-Abschnitte in der Courseware können nicht bearbeitet werden [#1618]
- Abschnitt Typ Liste stellt die Sortierung nicht da. [#1620]
- Icon für Termine auf "Meine Veranstaltungen" berücksichtigt auch ausgefallene Termine [#1643]
- Dateien mit großgeschriebener Dateiendung können nicht hochgeladen werden [#1644]
- Fehler beim Hinzufügen von Personen zu Sprechstunden über die Adminoberfläche [#1648]
- Veranstaltungen werden bei Gruppierung nicht mehr angezeigt [#1668]
- CW: l10n-Fehler beim Courseware-Reiter [#1680]
- Studienbereiche können nicht gelöscht werden auch bei alternativer LV-Gruppen-Zuordnung [#1681]
- Gelöschte Nutzer führen zu Fehlern in der Courseware [#1687]
- StudipDialog.vue berechnet die Position falsch [#1689]
- Freigabe von Seiten wird nicht vererbt [#1699]
- Terminvergabe: Terminblöcke nach dem Anlegen bearbeiten [#1707]
- Tabularasa-Aktion für Einrichtungen ist defekt [#1734]
- Courseware: Fehler beim Import ("Lege Ordner an") [#1738]
- Hinzufügen von Standardvertretungen funktioniert nicht mehr [#1743]
- führende und angehängte Leerzeichen in Suchfeldern ignorieren [#1765]
- Der Funktion getInfolabelPrperties fehlt ein O [#1767]
- Meine Einrichtungen: Klick auf eine neue Ankündigung führt in eine Exception [#1772]
- Meine Veranstaltungen lädt sich tot wenn ausgewähltes Semester nicht existiert [#1774]
- Filter nach Semestern bei der Suche nach Veranstaltungen über die JSONAPI ist defekt [#1775]
- Gruppenseite in einer VA: Bulk-Aktion „Nachricht schreiben“ schlägt fehl, wenn eine Person in mehreren Gruppen ist [#1776]
- Aufrufen der Seite "Zugangsberechtigungen" dauert sehr lange [#1779]
- Terminvergabe: Falsche Sortierung bei "Vergangene Termine" [#1785]
18.11.2022 v 4.6.7
https://gitlab.studip.de/studip/studip/-/issues?milestone_title=Stud.IP+4.6.7&state=all
- Falsche/feste Spaltenbreite in der Tabelle auf Admin > Log [#63]
- Sperrzeiten in der Vergangenheit können nicht bearbeitet werden [#185]
- Raumgruppen-Seriendruckfunktion ist nur für Raumadmins möglich [#201]
- Raumanfragen: Termine in der Vergangenheit werden mit angezeigt [#243]
- Datenfelder - Benötigter Status [#491]
- Manuelle Buchung: Fehlermeldung beim Umwandel von Wiederholungsterminen in Einzeltermine fehlt [#549]
- Plugin-Typen werden beim Update nicht aktualisiert [#569]
- PageLayout::postQuestion ist nach dem Aufruf nicht im Fokus und nicht barrierefrei [#609]
- Einzelbuchung einer Wiederholungsbuchung löschen funktioniert nicht immer [#704]
- Drucken von Belegungsplänen funktioniert für Dozenten nicht [#836]
- Manuelle Buchungen: Reservierungen können in den selben Raum kopiert werden [#840]
- Raumanfrage: Rüstzeit wird nicht mit angezeigt [#859]
- Termine kürzer als RESOURCES_MIN_BOOKING_TIME führen zu nicht auflösbaren Raumanfragen [#862]
- Blubber: Call to a member function getJSONData() on null [#864]
- Blubber Benachrichtigungen für Einrichtungen deaktivieren [#1021]
- Fehler im Code der Raumverwaltung [#1331]
- Unbekannte Variablen in class Course_StudygroupController::details_action() [#1337]
- PHP-Warnungen auf den externen Seiten [#1346]
- Sperrzeiten werden auf den Zeitpunkt der Buchung (nicht den zu buchenden Termin) angewendet [#1350]
- Ankündigungen bleiben nach dem Löschen eines Kurses zurück, wenn NEWS_DISABLE_GARBAGE_COLLECT aktiviert ist [#1355]
- Fullscreen Icon in Nav Bar zentriert [#1356]
- Stundenplan: Seltsames Pixelicon ersetzen [#1369]
- Performance der Gruppenpläne sehr schlecht [#1398]
- "Ordner bearbeiten" zeigt immer an, daß der Ordner keine Elemente enthält [#1402]
- MultiPersonSearch: Falsche Anzeige bei aufgelöstem Aktionsmenü [#1404]
- Druckansicht: Schrift in Tabellen wird kleiner [#1409]
- "Gruppe alphabetisch sortieren" unterscheidet Groß-/Kleinschreibung [#1410]
- Belegungsplan: Details zur Buchung verraten Veranstaltungsdetails zu VA-bezogenen Buchungen, die im Belegungsplan nicht angezeigt werden [#1411]
- Raumsuche: Einstellungen gehen nach der Suche verloren [#1422]
- Raumsuche: "Raumtyp" wird als Suchkriterium angeboten, obwohl es gar nicht belegt ist [#1423]
- Raumsuche: Ergebnisse sind nicht sortiert [#1425]
- Dateiverwaltung: Leere Dateinamen beim Herunterladen [#1426]
- Gruppenseite: Bulk-Aktion zum Ändern der Gruppengröße löst die Zuordnung der Gruppe zu einem Termin [#1427]
- Temporäre Rechtevergabe Bulkaction für Eintrag der Zeiten funktioniert nicht [#1428]
- Temporäre Rechtevergabe: nur 20 Teilnehmer aus Veranstaltung werden übernommen [#1429]
- VA-Administration: Klick auf TN-Zahl zeigt bei Hauptveranstaltungen auf die falsche URL [#1439]
- Raumattribut "room_type" kann nicht bearbeitet werden [#1440]
- Raumsuche: Enter schickt die Suche (manchmal) nicht ab [#1441]
- Migration 1.254 kann wegen doppelten Einträgen in der „hash“-Spalte der „opengraphdata“-Tabelle abbrechen [#1445]
- Anlegen einer Veranstaltung für Dozent zeigt keinen Dialog [#1455]
- Anmeldesets: Veranstaltungen konfigurieren für Dozenten nicht möglich [#1456]
- Berechtigungen für die gesamte Raumgruppe setzen - funktioniert nicht [#1462]
- data-activates und Dialoge funktionieren nicht richtig [#1490]
- Raumanfragen: Option für Rückmeldung an alle Lehrenden soll wieder immer verfügbar sein [#1494]
- Teilnehmerexport als csv zeigt Zwischenüberschriften "Lehrende" und "Studierende" [#1503]
- MvvPerm::getRoles() filtert Nutzerrollen falsch [#1546]
- PHP Warning: array_column() expects parameter 1 to be array, null given in app/controllers/course/members.php [#1548]
- Fehlende Abfrage, um Blubberbenachrichtigungen in Einrichtungen abzustellen [#1587]
- Fehlermeldung nach dem Anlegen einer Veranstaltung [#1595]
- Link zum Belegungsplan über einen QR-Code fordert zur Eingabe von Login-Daten auf [#1598]
- XSS-Probleme im Event-Log (Admin > Log) [#1619]
- Buchungen löschen schlägt über CLI fehl [#1623]
- Bei admin/courses wird die die erste Einrichtung statt alle Einrichtungen vorausgewählt [#1656]
- Hinter dem Namen eines Abschlusses steht immer "()", wenn kein Kurzname hinterlegt ist [#1669]
- json_encode() liefert leere Texte, wenn mehr als eine Sprache für Inhalte definiert ist [#1672]
- Typo im Template `app/views/messages/_message_row.php [#1673]
- Verwaltung der Nutzerdomänen: PHP fatal error: Allowed memory size exhausted [#1677]
- Fehler bei Terminvergabe, wenn Nutzer gelöscht wird [#1683]
- Der Belegungsplan wird nicht angezeigt, wenn eine Raumanfrage mit Rüstzeit für eine ganze Veranstaltung existiert, in der keine Termine sind [#1700]
- Fehler der Datenbankanbindung ist nicht aussagekräftig [#1716]
- Fragebögen: SQL-Fehler bei Suche nach Einrichtungen [#1727]
- Dateibereich: Optische Eigenheiten der Tabellen beheben [#1728]
- Anzeigefehler im Dialog zum Auswahl einer Datei [#1730]
- Konflikt zwischen Sprechstunden im Kern und dem alten Plugin [#1731]
- PHP Warning: count(): Parameter must be an array or an object that implements Countable [#1741]
- Veranstaltungsstundenplan: Studiengangteil läßt sich nicht abwählen [#1771]
- Benutzerverwaltung - Suche lässt sich nicht sortieren [#1781]
- Select mit submit-upon-select schickt das falsche Formular ab [#1783]
21.07.2022 v 5.1
https://gitlab.studip.de/studip/studip/-/issues?milestone_title=Stud.IP+5.1&state=all
- Trails: redirect() soll sich wie url_for() bedienen lassen [#1]
......
RELEASE 5.2.alpha-svn
RELEASE 5.2
......@@ -112,8 +112,6 @@ class Admin_CacheController extends AuthenticatedController
if (Config::get()->store('SYSTEMCACHE', $settings)) {
PageLayout::postSuccess(_('Die Einstellungen wurden gespeichert.'));
StudipCacheFactory::unconfigure();
} else {
PageLayout::postError(_('Die Einstellungen konnten nicht gespeichert werden.'));
}
$this->relocate('admin/cache/settings');
......
......@@ -22,10 +22,6 @@ class Admin_CourseplanningController extends AuthenticatedController
PageLayout::postError(_('Sie wurden noch keiner Einrichtung zugeordnet'));
}
if (!$GLOBALS['user']->cfg->MY_INSTITUTES_DEFAULT) {
$GLOBALS['user']->cfg->store('MY_INSTITUTES_DEFAULT', $this->insts[0]['Institut_id']);
}
// Semester selection
if ($GLOBALS['user']->cfg->MY_COURSES_SELECTED_CYCLE) {
$this->semester = Semester::find($GLOBALS['user']->cfg->MY_COURSES_SELECTED_CYCLE);
......@@ -631,13 +627,8 @@ class Admin_CourseplanningController extends AuthenticatedController
$stgteile = StudiengangTeil::getAllEnriched('fach_name','ASC', ['mvv_fach_inst.institut_id' => $GLOBALS['user']->cfg->MY_INSTITUTES_DEFAULT]);
$sidebar = Sidebar::Get();
$list = new SelectWidget(_('Studiengangteil'), $this->url_for('admin/courseplanning/set_selection/' . $this->selected_weekday), 'stgteil_select');
if ($this->selected_weekday) {
$list->addElement(new SelectElement('all', _('Alle')), 'stgteil_select-all');
}
$list->addElement(new SelectElement('all', _('Alle')), 'stgteil_select-all');
foreach ($stgteile as $stgteil) {
if (!$GLOBALS['user']->cfg->MY_COURSES_SELECTED_STGTEIL || ($GLOBALS['user']->cfg->MY_COURSES_SELECTED_STGTEIL == 'all' && !$this->selected_weekday)) {
$GLOBALS['user']->cfg->store('MY_COURSES_SELECTED_STGTEIL', $stgteil->id);
}
$list->addElement(new SelectElement(
$stgteil->id,
$stgteil->getDisplayName(),
......
......@@ -291,10 +291,6 @@ class Admin_CoursesController extends AuthenticatedController
PageLayout::postError(_('Sie wurden noch keiner Einrichtung zugeordnet'));
}
if (!$GLOBALS['user']->cfg->MY_INSTITUTES_DEFAULT) {
$GLOBALS['user']->cfg->store('MY_INSTITUTES_DEFAULT', $this->insts[0]['Institut_id']);
}
// Semester selection
if ($GLOBALS['user']->cfg->MY_COURSES_SELECTED_CYCLE) {
$this->semester = Semester::find($GLOBALS['user']->cfg->MY_COURSES_SELECTED_CYCLE);
......
......@@ -138,7 +138,7 @@ class Admin_DomainController extends AuthenticatedController
CSRFProtection::verifyUnsafeRequest();
$domain = new UserDomain($id);
if (count($domain->users) == 0) {
if ($domain->countUsers() === 0) {
$domain->delete();
} else {
PageLayout::postError(_('Domänen, denen noch Personen zugewiesen sind, können nicht gelöscht werden.'));
......
......@@ -60,6 +60,7 @@ class Admin_LoginStyleController extends AuthenticatedController
}
$extension = pathinfo($filename, PATHINFO_EXTENSION);
$extension = strtolower($extension);
if (!in_array($extension, ['gif', 'jpeg', 'jpg', 'png'])) {
continue;
}
......
......@@ -60,25 +60,6 @@ class Admin_UserController extends AuthenticatedController
$this->perm = $perm;
$request = '';
//Daten annehmen
if (Request::submitted('reset')) {
unset($_SESSION['admin']['user']);
} elseif (Request::submitted('search')) {
$request = $_SESSION['admin']['user'] = iterator_to_array(Request::getInstance());
}
//Suchparameter und Ergebnisse vorhanden
if (isset($_SESSION['admin']['user']) && $_SESSION['admin']['user']['results']) {
$request = $_SESSION['admin']['user'];
}
if (!empty($request)) {
// Inaktivität für die suche anpassen
$inaktiv = [$request['inaktiv'], $request['inaktiv_tage']];
if (empty($request['inaktiv_tage']) && $request['inaktiv'] != 'nie') {
$inaktiv = null;
}
}
//Datafields
$this->datafields = [];
......@@ -94,17 +75,46 @@ class Admin_UserController extends AuthenticatedController
return !$role->systemtype;
});
//wenn suche durchgeführt
if (!empty($request)) {
//Daten annehmen
if (Request::submitted('reset')) {
unset($_SESSION['admin']['user']);
} elseif (Request::submitted('search')) {
$request = iterator_to_array(Request::getInstance());
// Inaktivität für die suche anpassen
$inaktiv = [$request['inaktiv'], $request['inaktiv_tage']];
if (empty($request['inaktiv_tage']) && $request['inaktiv'] != 'nie') {
$inaktiv = null;
}
//suche mit datafields
$search_datafields = [];
foreach ($this->datafields as $datafield) {
if (mb_strlen($request[$datafield->id]) > 0
&& !(in_array($datafield->type, words('selectbox radio')) && $request[$datafield->id] === '---ignore---')
) {
$search_datafields[$datafield->id] = $request[$datafield->id];
$search_datafields[$datafield->id] = trim($request[$datafield->id]);
}
}
$request['username'] = trim($request['username']);
$request['email'] = trim($request['email']);
$request['vorname'] = trim($request['vorname']);
$request['nachname'] = trim($request['nachname']);
$request['inaktiv'] = $inaktiv;
$request['datafields'] = $search_datafields;
$_SESSION['admin']['user'] = $request;
} elseif (!empty($_SESSION['admin']['user']['results'])) {
//Suchparameter und Ergebnisse vorhanden
$request = $_SESSION['admin']['user'];
}
$this->request = [];
$this->users = [];
//wenn suche durchgeführt
if (!empty($request)) {
//Suchparameter
$this->sortby = Request::option('sortby', 'username');
$this->order = Request::option('order', 'asc');
......@@ -112,12 +122,9 @@ class Admin_UserController extends AuthenticatedController
$this->order = $this->order == 'desc' ? 'asc' : 'desc';
}
$request['vorname'] = $request['vorname'] ?: null;
$request['nachname'] = $request['nachname'] ?: null;
$request['inaktiv'] = $inaktiv;
$request['datafields'] = $search_datafields;
$request['sort'] = $this->sortby;
$request['order'] = $this->order;
$request['sortby'] = $this->sortby;
$request['order'] = $this->order;
$empty_search = $request['perm'] === 'alle';
$values = [
......
......@@ -518,7 +518,7 @@ class Admission_CoursesetController extends AuthenticatedController
$hidden = Request::intArray('configure_courses_hidden');
$ok = 0;
foreach($this->courses as $course) {
if ($GLOBALS['perm']->have_studip_perm('admin', $course->id)) {
if ($GLOBALS['perm']->have_studip_perm(Config::get()->ALLOW_DOZENT_COURSESET_ADMIN ? 'dozent' : 'admin', $course->id)) {
$do_update_admission = $course->admission_turnout < $admission_turnouts[$course->id];
$course->admission_turnout = $admission_turnouts[$course->id];
$course->admission_disable_waitlist = isset($admission_waitlists[$course->id]) ? 0 : 1;
......
......@@ -47,16 +47,16 @@ class BlubberController extends AuthenticatedController
$this->thread = array_pop($threads);
}
$this->thread_data = [];
if ($this->thread) {
$this->thread->markAsRead();
$this->thread_data = $this->thread->getJSONData(
50,
null,
Request::get("search")
);
}
$this->thread_data = $this->thread->getJSONData(
50,
null,
Request::get("search")
);
if (!Avatar::getAvatar($GLOBALS['user']->id)->is_customized() && !$_SESSION['already_asked_for_avatar']) {
$_SESSION['already_asked_for_avatar'] = true;
PageLayout::postInfo(sprintf(
......
......@@ -103,18 +103,18 @@ class Consultation_AdminController extends ConsultationController
if ($GLOBALS['user']->cfg->CONSULTATION_SHOW_GROUPED) {
$this->blocks = $this->groupSlots(ConsultationSlot::findByRange(
$this->range,
"ORDER BY start ASC LIMIT " . ($this->page * $this->limit) . ", {$this->limit}",
"ORDER BY start DESC LIMIT " . ($this->page * $this->limit) . ", {$this->limit}",
true
));
} else {
$this->blocks = ConsultationBlock::findByRange(
$this->range,
'ORDER BY start ASC',
'ORDER BY start DESC',
true
);
$this->slots = ConsultationSlot::findByRange(
$this->range,
"ORDER BY start ASC LIMIT " . ($this->page * $this->limit) . ", {$this->limit}",
"ORDER BY start DESC LIMIT " . ($this->page * $this->limit) . ", {$this->limit}",
true
);
}
......@@ -160,14 +160,26 @@ class Consultation_AdminController extends ConsultationController
throw new InvalidArgumentException(_('Die Endzeit liegt vor der Startzeit!'));
}
$slot_count = ConsultationBlock::countBlocks(
// Determine duration of a slot and pause times
$duration = Request::int('duration');
$pause_time = Request::bool('pause') ? Request::int('pause_time') : null;
$pause_duration = Request::bool('pause') ? Request::int('pause_duration') : null;
if ($pause_time && $pause_time < $duration) {
throw new InvalidArgumentException(_('Die definierte Zeit bis zur Pause ist kleiner als die Dauer eines Termins.'));
}
if ($this->range instanceof Institute && !Request::getArray('responsibilities')) {
throw new InvalidArgumentException(_('Es muss mindestens eine durchführende Person, Statusgruppe oder Einrichtung ausgewählt werden.'));
}
$slot_count = ConsultationBlock::countSlots(
$start,
$end,
Request::int('day-of-week'),
Request::int('interval'),
Request::int('duration'),
Request::bool('pause') ? Request::int('pause_time') : null,
Request::bool('pause') ? Request::int('pause_duration') : null
$pause_time,
$pause_duration
);
if ($slot_count >= self::SLOT_COUNT_THRESHOLD && !Request::int('confirmed')) {
$this->flash['confirm-many'] = $slot_count;
......@@ -192,11 +204,13 @@ class Consultation_AdminController extends ConsultationController
$block->note = Request::get('note');
$block->size = Request::int('size', 1);
$block->createSlots(
Request::int('duration'),
Request::bool('pause') ? Request::int('pause_time') : null,
Request::bool('pause') ? Request::int('pause_duration') : null
);
$slots = $block->createSlots(Request::int('duration'), $pause_time, $pause_duration);
if (count($slots) === 0) {
continue;
}
$block->slots->exchangeArray($slots);
$stored += $block->store();
// Store block responsibilites
......@@ -329,9 +343,8 @@ class Consultation_AdminController extends ConsultationController
if ($this->range instanceof Course) {
$this->search_object = new PermissionSearch('user_in_sem', _('Person suchen'), 'user_id', [
'seminar_id' => $this->range->getRangeId(),
'sem_perm' => ['user', 'autor'],
'sem_perm' => $permissions,
]);
}
if (Request::isPost()) {
......@@ -373,6 +386,11 @@ class Consultation_AdminController extends ConsultationController
$this->block = $this->loadBlock($block_id);
$this->block->room = trim(Request::get('room'));
$this->block->note = trim(Request::get('note'));
$this->block->size = Request::int('size');
$this->block->calendar_events = Request::bool('calender-events', false);
$this->block->show_participants = Request::bool('show-participants', false);
$this->block->require_reason = Request::option('require-reason');
$this->block->confirmation_text = trim(Request::get('confirmation-text'));
foreach ($this->block->slots as $slot) {
$slot->note = '';
......@@ -797,20 +815,20 @@ class Consultation_AdminController extends ConsultationController
$options->addCheckbox(
_('Benachrichtungen über Buchungen'),
$this->getUserConfig()->getValue('CONSULTATION_SEND_MESSAGES'),
$this->toggleURL('messages/1', $action === 'expired'),
$this->toggleURL('messages/0', $action === 'expired')
$this->toggleURL('messages', 1, $action === 'expired'),
$this->toggleURL('messages', 0, $action === 'expired')
);
$options->addCheckbox(
_('Abgelaufene Terminblöcke automatisch löschen'),
$config->CONSULTATION_GARBAGE_COLLECT,
$this->toggleURL('garbage/1', $action === 'expired'),
$this->toggleURL('garbage/0', $action === 'expired')
$this->toggleURL('garbage', 1, $action === 'expired'),
$this->toggleURL('garbage', 0, $action === 'expired')
);
$options->addCheckbox(
_('Termine gruppiert anzeigen'),
$this->getUserConfig()->getValue('CONSULTATION_SHOW_GROUPED'),
$this->toggleURL('grouped/1', $action === 'expired'),
$this->toggleURL('grouped/0', $action === 'expired')
$this->toggleURL('grouped', 1, $action === 'expired'),
$this->toggleURL('grouped', 0, $action === 'expired')
);
$export = $sidebar->addWidget(new ExportWidget());
......
......@@ -82,7 +82,8 @@ class Course_AdmissionController extends AuthenticatedController
$this->activated_admission_rules = AdmissionRule::getAvailableAdmissionRules();
if (!$this->current_courseset) {
$available_coursesets = new SimpleCollection();
foreach (CourseSet::getCoursesetsByInstituteId($this->course->institut_id) as $cs) {
$filter = ['course_set_chdate' => strtotime('-1 year')];
foreach (CourseSet::getCoursesetsByInstituteId($this->course->institut_id, $filter) as $cs) {
$cs = new CourseSet($cs['set_id']);
if ($cs->isUserAllowedToAssignCourse($this->user_id, $this->course_id)) {
$available_coursesets[] = ['id' => $cs->getId(),
......@@ -91,7 +92,7 @@ class Course_AdmissionController extends AuthenticatedController
'my_own' => $cs->getUserId() === $GLOBALS['user']->id];
}
}
foreach (CourseSet::getglobalCoursesets() as $cs) {
foreach (CourseSet::getglobalCoursesets($filter) as $cs) {
$cs = new CourseSet($cs['set_id']);
if ($cs->isUserAllowedToAssignCourse($this->user_id, $this->course_id)) {
$available_coursesets[] = ['id' => $cs->getId(),
......@@ -100,7 +101,6 @@ class Course_AdmissionController extends AuthenticatedController
'my_own' => $cs->getUserId() === $GLOBALS['user']->id];
}
}
$available_coursesets = $available_coursesets->findBy('chdate', strtotime('-1 year'), '>');
$available_coursesets->orderBy('name');
$this->available_coursesets = $available_coursesets;
......
......@@ -632,8 +632,8 @@ class Course_BasicdataController extends AuthenticatedController
$lecturers = $sem->getMembers();
foreach ($deputies as $deputy) {
// ..but only if not already set as lecturer or deputy.
if (!isset($lecturers[$deputy['user_id']]) && !Deputy::isDeputy($deputy['user_id'], $course_id)) {
Deputy::addDeputy($deputy['user_id'], $course_id);
if (!isset($lecturers[$deputy])) {
Deputy::addDeputy($deputy, $course_id);
}
}
}
......
......@@ -133,6 +133,22 @@ class Course_BlockAppointmentsController extends AuthenticatedController
}
}
//Calculate the duration if a minimum booking time is set:
if (Config::get()->RESOURCES_MIN_BOOKING_TIME) {
$fake_start_time = strtotime(Request::get('block_appointments_start_time'), $start_day);
$fake_end_time = strtotime(Request::get('block_appointments_end_time'), $start_day);
$duration = $fake_end_time - $fake_start_time;
if ($duration < Config::get()->RESOURCES_MIN_BOOKING_TIME * 60) {
$errors[] = sprintf(
ngettext(
'Die minimale Dauer eines Termins von einer Minute wurde unterschritten.',
'Die minimale Dauer eines Termins von %u Minuten wurde unterschritten.',
Config::get()->RESOURCES_MIN_BOOKING_TIME
),
Config::get()->RESOURCES_MIN_BOOKING_TIME
);
}
}
$termin_typ = Request::int('block_appointments_termin_typ', 0);
$free_room_text = Request::get('block_appointments_room_text');
......
......@@ -103,8 +103,8 @@ class Course_CoursewareController extends AuthenticatedController
public function pdf_export_action($element_id, $with_children)
{
$element = \Courseware\StructuralElement::findOneById($element_id);
$this->render_pdf($element->pdfExport($this->user, $with_children), trim($element->title).'.pdf');
$user = User::find($GLOBALS['user']->id);
$this->render_pdf($element->pdfExport($user, $with_children), trim($element->title).'.pdf');
}
private function setIndexSidebar(): void
......@@ -229,7 +229,7 @@ class Course_CoursewareController extends AuthenticatedController
foreach ($blks as $blk) {
$progresses = $userProgresses[$blk];
$usersProgress = $progresses['count'] ? (float) $progresses['grade'] : 0;
$data['progress'] += $usersProgress / $usersCounter;
$data['progress'] += $usersCounter ? $usersProgress / $usersCounter : 0;
}
return $data;
......
......@@ -286,7 +286,7 @@ class Course_Forum_IndexController extends ForumController
function search_action($page = null)
{
if (Request::submitted('reset-search')) {
$this->redirect('index');
$this->redirect('course/forum/index/index');
return;
}
......
......@@ -156,7 +156,7 @@ class Course_IliasInterfaceController extends AuthenticatedController
[
'data-confirm' => sprintf(
_('Verknüpfung zum Kurs in %s entfernen? Hierdurch werden auch die Verknüpfungen zu allen Objekten innerhalb des Kurses entfernt.'),
htmlReady($this->ilias_list[$ilias_index]->getName())
$this->ilias_list[$ilias_index]->getName()
)
]
);
......
......@@ -451,26 +451,23 @@ class Course_MembersController extends AuthenticatedController
global $perm;
if ($perm->have_perm('root')) {
$parameters = [
'semtypes' => studygroup_sem_types() ?: [],
'semtypes' => studygroup_sem_types() ?: null,
'exclude' => [Context::getId()],
'semesters' => array_map(function ($s) { return $s->semester_id; }, Semester::getAll())
];
} else if ($perm->have_perm('admin')) {
$parameters = [
'semtypes' => studygroup_sem_types() ?: [],
'semtypes' => studygroup_sem_types() ?: null,
'institutes' => array_map(function ($i) {
return $i['Institut_id'];
}, Institute::getMyInstitutes()),
'exclude' => [Context::getId()],
'semesters' => array_map(function ($s) { return $s->semester_id; }, Semester::getAll())
];
} else {
$parameters = [
'userid' => $GLOBALS['user']->id,
'semtypes' => studygroup_sem_types() ?: [],
'semtypes' => studygroup_sem_types() ?: null,
'exclude' => [Context::getId()],
'semesters' => array_map(function ($s) { return $s->semester_id; }, Semester::getAll())
];
}
$coursesearch = MyCoursesSearch::get('Seminar_id', $GLOBALS['perm']->get_perm(), $parameters);
......@@ -483,23 +480,21 @@ class Course_MembersController extends AuthenticatedController
if (!empty($this->flash['users']) || Request::getArray('users')) {
$users = $this->flash['users'] ?: Request::getArray('users');
// create a usable array
foreach ($this->flash['users'] as $user => $val) {
foreach ($users as $user => $val) {
if ($val) {
$this->users[] = $user;
}
}
PageLayout::setTitle( _('Zielveranstaltung auswählen'));
} elseif (Request::isXhr()) {
$this->response->add_header('X-Dialog-Close', '1');
$this->render_nothing();
} else {
if (Request::isXhr()) {
$this->response->add_header('X-Dialog-Close', '1');
$this->render_nothing();
} else {
$this->redirect('course/members/index');
}
}
}
}
/**
* Copies or moves selected users to the selected target course.
......@@ -564,7 +559,6 @@ class Course_MembersController extends AuthenticatedController
$this->redirect(URLHelper::getURL('dispatch.php/messages/write', [
'default_subject' => $this->getSubject(),
'tmpsavesnd' => 1,
'course_id' => $this->course_id,
'emailrequest' => 1
]));
} else {
......@@ -1837,6 +1831,8 @@ class Course_MembersController extends AuthenticatedController
$this->tutor_name = get_title_for_status('tutor', 0, $sem->status);
$this->dozent_name = get_title_for_status('dozent', 0, $sem->status);
$this->default_subject = Request::get('default_subject');
if ($this->is_tutor) {
$this->awaiting_count = AdmissionApplication::countBySql(
"seminar_id = :course_id AND status = 'awaiting'",
......@@ -1878,7 +1874,7 @@ class Course_MembersController extends AuthenticatedController
'dispatch.php/messages/write',
[
'course_id' => $this->course_id,
'default_subject' => $this->subject,
'default_subject' => $this->default_subject,
'filter' => 'all',
'emailrequest' => 1
]
......@@ -1888,7 +1884,7 @@ class Course_MembersController extends AuthenticatedController
'dispatch.php/messages/write',
[
'course_id' => $this->course_id,
'default_subject' => $this->subject,
'default_subject' => $this->default_subject,
'filter' => 'really_all',
'emailrequest' => 1
]
......@@ -1927,7 +1923,7 @@ class Course_MembersController extends AuthenticatedController
$url_params = [
'course_id' => $this->course_id,
'default_subject' => $this->subject,
'default_subject' => $this->default_subject,
'filter' => implode(',', array_unique($filters)),
'emailrequest' => 1
];
......
......@@ -94,7 +94,8 @@ class Course_StudyAreasController extends AuthenticatedController
if (Request::get('open_node')) {
$this->values[get_class($this->step)]['open_node'] = Request::get('open_node');
}
$this->must_have_studyareas = $this->is_required();
$this->is_activated = $this->is_activated();
$this->is_required = $this->is_required();
$this->values[get_class($this->step)]['locked'] = $this->locked;
$this->tree = $this->step->getStepTemplate($this->values, 0, 0);
......@@ -148,7 +149,6 @@ class Course_StudyAreasController extends AuthenticatedController
$msg = $this->unassign();
}
} else {
$studyareas = Request::getArray('studyareas');
......@@ -157,13 +157,12 @@ class Course_StudyAreasController extends AuthenticatedController
$this->redirect($url);
return;
}
if (!empty($studyareas) && !$this->is_required()) {
PageLayout::postMessage(MessageBox::error(_('Sie dürfen keine Studienbereiche zuweisen.')));
if (!empty($studyareas) && !$this->is_activated()) {
PageLayout::postError(_('Sie dürfen keine Studienbereiche zuweisen.'));
$this->redirect($url);
return;
}
try {
$this->course->setStudyAreas($studyareas);
} catch (UnexpectedValueException $e) {
......@@ -226,6 +225,21 @@ class Course_StudyAreasController extends AuthenticatedController
* @return boolean True if required.
*/
private function is_required()
{
$sem_class = $this->course->getSemClass();
if (get_class($this->step) === 'StudyAreasLVGroupsCombinedWizardStep') {
if ($sem_class['module']) {
$lv_gruppen = Lvgruppe::findBySeminar($this->course->id);
if (count($lv_gruppen)) {
return false;
}
}
}
return (bool) $sem_class['bereiche'];
}
private function is_activated()
{
$sem_class = $this->course->getSemClass();
return (bool) $sem_class['bereiche'];
......
......@@ -106,6 +106,13 @@ class Course_TimesroomsController extends AuthenticatedController
}
}
protected function bookingTooShort(int $start_time, int $end_time)
{
return Config::get()->RESOURCES_MIN_BOOKING_TIME &&
(($end_time - $start_time) < Config::get()->RESOURCES_MIN_BOOKING_TIME * 60);
}
/**
* Displays the times and rooms of a course
*
......@@ -362,6 +369,20 @@ class Course_TimesroomsController extends AuthenticatedController
$end_time = $termin->end_time;
PageLayout::postError(_('Die Zeitangaben sind nicht korrekt. Bitte überprüfen Sie diese!'));
}
if ($this->bookingTooShort($date, $end_time)) {
PageLayout::postError(
sprintf(
ngettext(
'Die minimale Dauer eines Termins von einer Minute wurde unterschritten.',
'Die minimale Dauer eines Termins von %u Minuten wurde unterschritten.',
Config::get()->RESOURCES_MIN_BOOKING_TIME
),
Config::get()->RESOURCES_MIN_BOOKING_TIME
)
);
$this->redirect('course/timesrooms/editDate/' . $termin_id, ['contentbox_open' => $termin->metadate_id]);
return;
}
$time_changed = ($date != $termin->date || $end_time != $termin->end_time);
//time changed for regular date. create normal singledate and cancel the regular date
......@@ -520,6 +541,20 @@ class Course_TimesroomsController extends AuthenticatedController
return;
}
if ($this->bookingTooShort($start_time, $end_time)) {
PageLayout::postError(
sprintf(
ngettext(
'Die minimale Dauer eines Termins von einer Minute wurde unterschritten.',
'Die minimale Dauer eines Termins von %u Minuten wurde unterschritten.',
Config::get()->RESOURCES_MIN_BOOKING_TIME
),
Config::get()->RESOURCES_MIN_BOOKING_TIME
)
);
$this->redirect('course/timesrooms/createSingleDate');
return;
}
$termin = new CourseDate();
$termin->termin_id = $termin->getNewId();
......@@ -1161,6 +1196,20 @@ class Course_TimesroomsController extends AuthenticatedController
return;
}
if ($this->bookingTooShort($start, $end)) {
PageLayout::postError(
sprintf(
ngettext(
'Die minimale Dauer eines Termins von einer Minute wurde unterschritten.',
'Die minimale Dauer eines Termins von %u Minuten wurde unterschritten.',
Config::get()->RESOURCES_MIN_BOOKING_TIME
),
Config::get()->RESOURCES_MIN_BOOKING_TIME
)
);
$this->redirect('course/timesrooms/createCycle');
return;
}
$cycle = new SeminarCycleDate();
$cycle->seminar_id = $this->course->id;
......@@ -1219,6 +1268,23 @@ class Course_TimesroomsController extends AuthenticatedController
$cycle->start_time = date('H:i:00', $start);
$cycle->end_time = date('H:i:00', $end);
}
//Check the duration:
if ($this->bookingTooShort($start, $end)) {
PageLayout::postError(
sprintf(
ngettext(
'Die minimale Dauer eines Termins von einer Minute wurde unterschritten.',
'Die minimale Dauer eines Termins von %u Minuten wurde unterschritten.',
Config::get()->RESOURCES_MIN_BOOKING_TIME
),
Config::get()->RESOURCES_MIN_BOOKING_TIME
)
);
$this->redirect('course/timesrooms/createCycle/' . $cycle_id);
return;
}
$cycle->weekday = Request::int('day');
$cycle->description = Request::get('description');
$cycle->sws = Request::get('teacher_sws');
......