Select Git revision
-
Moritz Strohm authoredMoritz Strohm authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
admin.php 30.91 KiB
<?php
/**
* This file is part of the TandemPlugin for Stud.IP
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* @author Moritz Strohm <strohm@data-quest.de>
* @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
* @category Plugin
**/
require_once(__DIR__ . '/../models/TandemProfile.class.php');
require_once(__DIR__ . '/../models/TandemPair.class.php');
require_once(__DIR__ . '/../models/BlocklistEntry.class.php');
class AdminController extends PluginController
{
public function before_filter(&$action, &$args)
{
parent::before_filter($action, $args);
global $perm;
//Only root and TandemAdmin users can access this area!
if(!RolePersistence::isAssignedRole(User::findCurrent()->id, 'TandemAdmin') and !$perm->have_perm('root')) {
throw new AccessDeniedException();
}
$this->admin_nav_path = '/tandemplugin/admin';
if (Config::get()->TANDEMPLUGIN_USE_TOOLS_NAVIGATION) {
if ($this->plugin->isOldStudip()) {
$this->admin_nav_path = '/tools/tandemplugin';
} else {
$this->admin_nav_path = '/contents/tandemplugin';
}
}
}
public function pairs_action()
{
//build sidebar:
$this->status = (int)Request::get('status', 1);
$sidebar = Sidebar::get();
$actions = new ActionsWidget();
$actions->addLink(
dgettext('TandemPlugin', 'CSV-Export'),
PluginEngine::getURL(
$this->plugin,
['status' => $this->status, 'csv_export' => '1'],
'admin/pairs'
),
Icon::create('file-excel', 'clickable')
);
$sidebar->addWidget($actions);
if(($this->status < -1) or ($this->status > 1)) {
$this->status = 1;
}
if($this->status == -1) {
if(Navigation::hasItem($this->admin_nav_path . '/rejected')) {
Navigation::activateItem($this->admin_nav_path . '/rejected');
}
} elseif($this->status == 0) {
if(Navigation::hasItem($this->admin_nav_path . '/requested')) {
Navigation::activateItem($this->admin_nav_path . '/requested');
}
} elseif($this->status == 1) {
if(Navigation::hasItem($this->admin_nav_path . '/established')) {
Navigation::activateItem($this->admin_nav_path . '/established');
}
}
$this->pairs = [];
$this->pairs = TandemPair::findBySql(
'status = :status',
['status' => $this->status]
);
if(Request::get('csv_export')) {
//A CSV file with all pairs shall be created instead of
//showing the view.
$csv_data = [];
if (Config::get()->TANDEMPLUGIN_PROOF_FIELDS_ENABLED) {
$csv_data[] = [
'name1', 'vorname1', 'email1', 'studiengang1', 'geschlecht1',
'beherrschte_sprache1', 'lernsprache1', 'Scheininteresse1',
'name2', 'vorname2', 'email2', 'studiengang2', 'geschlecht2',
'beherrschte_sprache2', 'lernsprache2', 'Scheininteresse2',
'paarzeitaktiv'
];
} else {
$csv_data[] = [
'name1', 'vorname1', 'email1', 'studiengang1', 'geschlecht1',
'beherrschte_sprache1', 'lernsprache1',
'name2', 'vorname2', 'email2', 'studiengang2', 'geschlecht2',
'beherrschte_sprache2', 'lernsprache2',
'paarzeitaktiv'
];
}
foreach($this->pairs as $pair) {
$user1_study_names = [];
if($pair->request->user->studycourses) {
foreach($pair->request->user->studycourses as $studycourse) {
$user1_study_names[] = $studycourse->studycourse->name;
}
}
$user1_proofs = '';
if (Config::get()->TANDEMPLUGIN_PROOF_FIELDS_ENABLED) {
if($pair->request->proof_of_achievement) {
$user1_proofs .= 'L';
}
if($pair->request->proof_of_attendance) {
$user1_proofs .= 'T';
}
}
$user2_study_names = [];
if($pair->offer->user->studycourses) {
foreach($pair->offer->user->studycourses as $studycourse) {
$user2_study_names[] = $studycourse->studycourse->name;
}
}
$user2_proofs = '';
if (Config::get()->TANDEMPLUGIN_PROOF_FIELDS_ENABLED) {
if($pair->offer->proof_of_achievement) {
$user2_proofs .= 'L';
}
if($pair->offer->proof_of_attendance) {
$user2_proofs .= 'T';
}
}
$requester_sex = '?';
if ($pair->request->user->geschlecht == '1') {
$requester_sex = 'm';
} elseif ($pair->request->user->geschlecht == '2') {
$requester_sex = 'w';
}
$offerer_sex = '?';
if ($pair->offer->user->geschlecht == '1') {
$offerer_sex = 'm';
} elseif ($pair->offer->user->geschlecht == '2') {
$offerer_sex = 'w';
}
if (Config::get()->TANDEMPLUGIN_PROOF_FIELDS_ENABLED) {
$csv_data[] = [
$pair->request->user->nachname,
$pair->request->user->vorname,
$pair->request->user->email,
implode(',', $user1_study_names),
$requester_sex,
$pair->offer->target_language_id,
$pair->request->target_language_id,
$user1_proofs,
$pair->offer->user->nachname,
$pair->offer->user->vorname,
$pair->offer->user->email,
implode(',', $user2_study_names),
$offerer_sex,
$pair->request->target_language_id,
$pair->offer->target_language_id,
$user2_proofs,
date('d.m.Y H:i', $pair->chdate)
];
} else {
$csv_data[] = [
$pair->request->user->nachname,
$pair->request->user->vorname,
$pair->request->user->email,
implode(',', $user1_study_names),
$requester_sex,
$pair->offer->target_language_id,
$pair->request->target_language_id,
$pair->offer->user->nachname,
$pair->offer->user->vorname,
$pair->offer->user->email,
implode(',', $user2_study_names),
$offerer_sex,
$pair->request->target_language_id,
$pair->offer->target_language_id,
date('d.m.Y H:i', $pair->chdate)
];
}
}
//The CSV file's content was created. Now we can send it:
$csv_text = array_to_csv($csv_data);
$this->set_content_type('text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename=' .
dgettext('TandemPlugin', 'Tandem-Paare') .
'_' . date('Y-m-d') . '.csv');
//For Content-Length we must use strlen instead of mb_strlen
//to get the number of bytes rather than the number of characters:
header('Content-Length: ' . strlen($csv_text));
$this->render_text($csv_text);
}
}
public function terminated_pairs_action()
{
$sidebar = Sidebar::get();
$actions = new ActionsWidget();
$actions->addLink(
dgettext('TandemPlugin', 'CSV-Export'),
PluginEngine::getURL(
$this->plugin,
['csv_export' => '1'],
'admin/terminated_pairs'
),
Icon::create('file-excel', 'clickable')
);
$sidebar->addWidget($actions);
if(Navigation::hasItem($this->admin_nav_path . '/terminated')) {
Navigation::activateItem($this->admin_nav_path . '/terminated');
}
$this->terminated_pairs = [];
$this->terminated_pairs = TerminatedTandemPair::findBySql('TRUE ORDER BY `mkdate` DESC');
if(Request::get('csv_export')) {
//A CSV file with all terminated pairs shall be created instead of
//showing the view.
$csv_data = [];
$csv_data[] =[
'name1', 'vorname1', 'email1', 'studiengang1', 'geschlecht1',
'beherrschte_sprache1', 'lernsprache1',
'name2', 'vorname2', 'email2', 'studiengang2', 'geschlecht2',
'beherrschte_sprache2', 'lernsprache2',
'datum_auflösung'
];
foreach($this->terminated_pairs as $pair) {
$user1_study_names = [];
if($pair->requester->studycourses) {
foreach($pair->requester->studycourses as $studycourse) {
$user1_study_names[] = $studycourse->studycourse->name;
}
}
$user2_study_names = [];
if($pair->offerer->studycourses) {
foreach($pair->offerer->studycourses as $studycourse) {
$user2_study_names[] = $studycourse->studycourse->name;
}
}
$requester_sex = '?';
if ($pair->requester->geschlecht == '1') {
$requester_sex = 'm';
} elseif ($pair->requester->geschlecht == '2') {
$requester_sex = 'w';
}
$offerer_sex = '?';
if ($pair->offerer->geschlecht == '1') {
$offerer_sex = 'm';
} elseif ($pair->offerer->geschlecht == '2') {
$offerer_sex = 'w';
}
$csv_data[] = [
$pair->requester->nachname,
$pair->requester->vorname,
$pair->requester->email,
implode(',', $user1_study_names),
$requester_sex,
$pair->offerer_language_id,
$pair->requester_language_id,
$pair->offerer->nachname,
$pair->offerer->vorname,
$pair->offerer->email,
implode(',', $user2_study_names),
$offerer_sex,
$pair->requester_language_id,
$pair->offerer_language_id,
date('d.m.Y H:i', $pair->mkdate)
];
}
//The CSV file's content was created. Now we can send it:
$csv_text = array_to_csv($csv_data);
$this->set_content_type('text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename=' .
dgettext('TandemPlugin', 'Aufgelöste_Tandems') .
'_' . date('Y-m-d') . '.csv');
//For Content-Length we must use strlen instead of mb_strlen
//to get the number of bytes rather than the number of characters:
header('Content-Length: ' . strlen($csv_text));
$this->render_text($csv_text);
}
}
public function search_action()
{
if(Navigation::hasItem($this->admin_nav_path . '/search')) {
Navigation::activateItem($this->admin_nav_path . '/search');
}
$this->age_of_request = 0;
$this->all_languages = TandemLanguage::findAll();
if (Request::submitted('search') or Request::submitted('export')) {
if (Request::submitted('search')) {
$this->search_requested = true;
CSRFProtection::verifyUnsafeRequest();
}
$this->mother_language_id = trim(Request::get('mother_language_id'));
$this->target_language_id = trim(Request::get('target_language_id'));
$this->age_of_request = intval(Request::get('age_of_request'));
if (!$this->mother_language_id) {
PageLayout::postError(
dgettext(
'TandemPlugin',
'Zur Suche muss eine beherrschte Sprache ausgewählt werden!'
)
);
return;
}
$this->mother_language = TandemLanguage::find(
$this->mother_language_id
);
$this->target_language = TandemLanguage::find(
$this->target_language_id
);
if (!$this->mother_language) {
PageLayout::postError(
dgettext(
'TandemPlugin',
'Die gewählte beherrschte Sprache wurde nicht in der Datenbank gefunden!'
)
);
return;
}
$sql = "INNER JOIN tandem_user_mother_languages
USING (user_id)
WHERE
tandem_user_mother_languages.language_id = :mother_language_id ";
$sql_array = [
'mother_language_id' => $this->mother_language_id
];
if ($this->target_language_id) {
if (!$this->target_language) {
PageLayout::postError(
dgettext(
'TandemPlugin',
'Die gewählte Zielsprache wurde nicht in der Datenbank gefunden!'
)
);
return;
}
$sql .= "AND
tandem_profiles.target_language_id = :target_language_id ";
$sql_array['target_language_id'] = $this->target_language_id;
}
if ($this->age_of_request > 0) {
$minimum_mkdate = new DateTime();
$minimum_mkdate = $minimum_mkdate->sub(
new DateInterval('P' . $this->age_of_request . 'D')
);
$minimum_mkdate->setTime(0,0,0);
$sql .= "AND tandem_profiles.mkdate <= :minimum_mkdate ";
$sql_array['minimum_mkdate'] = $minimum_mkdate->getTimestamp();
}
$sidebar = Sidebar::get();
$actions = new ActionsWidget();
$actions->addLink(
dgettext('TandemPlugin', 'CSV-Export'),
PluginEngine::getURL(
$this->plugin,
[
'mother_language_id' => $this->mother_language_id,
'target_language_id' => $this->target_language_id,
'age_of_request' => $this->age_of_request,
'export' => '1'
],
'admin/search'
),
Icon::create('file-excel', 'clickable')
);
$sidebar->addWidget($actions);
$minimum_mkdate = new DateTime();
$minimum_mkdate = $minimum_mkdate->sub(
new DateInterval('P' . $this->age_of_request . 'D')
);
$minimum_mkdate->setTime(0,0,0);
$this->search_results = TandemProfile::findBySql($sql, $sql_array);
if (Request::submitted('export')) {
//Instead of displaying the search results we shall export them:
$csv_array = [
[
dgettext('TandemPlugin', 'Name'),
dgettext('TandemPlugin', 'E-Mail Adresse'),
dgettext('TandemPlugin', 'Beherrschte Sprache - Zielsprache'),
dgettext('TandemPlugin', 'Gesuch eingestellt am')
]
];
foreach ($this->search_results as $search_result) {
$csv_array[] = [
(
$search_result->user
? $search_result->user->getFullName()
: dgettext('TandemPlugin', 'unbekannt')
),
$search_result->user->email,
$this->mother_language->getLocalName() .
' - ' .
(
$search_result->target_language
? $search_result->target_language->getLocalName()
: dgettext('TandemPlugin', 'Unbekannte Sprache')
),
date('d.m.Y H:i', $search_result->mkdate)
];
}
$csv_text = array_to_csv($csv_array);
$this->set_content_type('text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename=' .
dgettext('TandemPlugin', 'Tandem-Gesuche') .
'-' .
$this->mother_language_id .
'-' .
$this->target_language_id .
'-' .
$this->age_of_request .
'_' .
date('Y-m-d') .
'.csv'
);
//For Content-Length we must use strlen instead of mb_strlen
//to get the number of bytes rather than the number of characters:
header('Content-Length: ' . strlen($csv_text));
$this->render_text($csv_text);
}
}
}
public function config_action()
{
if(Navigation::hasItem($this->admin_nav_path . '/config')) {
Navigation::activateItem($this->admin_nav_path . '/config');
}
if(Navigation::hasItem('/profile/tandem_administration/config')) {
Navigation::activateItem('/profile/tandem_administration/config');
}
$config = Config::get();
if(Request::submitted('save')) {
CSRFProtection::verifyUnsafeRequest();
$this->gender_search_enabled = (bool)Request::get('gender_search_enabled', false);
$this->delete_old_period = (int)Request::int('delete_old_period', 6);
$this->proof_fields_enabled = (bool)Request::get('proof_fields_enabled', false);
$this->use_tools_navigation = Request::int('use_tools_navigation', 0);
$this->management_email_address = Request::get('management_email_address');
$this->use_level = (bool)Request::get('use_level', false);
if(($this->delete_old_period < 1) or ($this->delete_old_period > 24)) {
PageLayout::postError(
dgettext('TandemPlugin', 'Die Anzahl an Monaten, nach denen alte Gesuche entfernt werden sollen, muss zwischen 1 und 24 liegen!')
);
return;
}
//get the config entries and store them:
$proof_fields_enabled = ConfigEntry::findByField('TANDEMPLUGIN_PROOF_FIELDS_ENABLED')[0];
if($proof_fields_enabled) {
$proof_fields_enabled->value = (int)$this->proof_fields_enabled;
$proof_fields_enabled->store();
}
$gender_search_enabled = ConfigEntry::findByField('TANDEMPLUGIN_GENDER_SEARCH_ENABLED')[0];
if($gender_search_enabled) {
$gender_search_enabled->value = (int)$this->gender_search_enabled;
$gender_search_enabled->store();
}
$delete_old_period = ConfigEntry::findByField('TANDEMPLUGIN_DELETE_OLD_PERIOD')[0];
if($delete_old_period) {
$delete_old_period->value = $this->delete_old_period;
$delete_old_period->store();
}
$management_email_address_field = ConfigEntry::findByField('TANDEMPLUGIN_MANAGEMENT_EMAIL_ADDRESS')[0];
if ($management_email_address_field) {
$management_email_address_field->value = $this->management_email_address;
$management_email_address_field->store();
}
$use_level = ConfigEntry::findByField('TANDEMPLUGIN_USE_LEVEL')[0];
if($use_level) {
$use_level->value = $this->use_level;
$use_level->store();
}
$config->store(
'TANDEMPLUGIN_USE_TOOLS_NAVIGATION',
(int)$this->use_tools_navigation
);
PageLayout::postSuccess(
dgettext('TandemPlugin', 'Die Konfiguration wurde gespeichert!')
);
//Reload page to avoid POST requests in browser history
//and to avoid the obsolet navigation path to be shown,
//if the navigation path for the tandem administration
//has been changed.
$this->redirect('admin/config');
} else {
$this->proof_fields_enabled = (bool)
($config->TANDEMPLUGIN_PROOF_FIELDS_ENABLED ?
$config->TANDEMPLUGIN_PROOF_FIELDS_ENABLED : false);
$this->gender_search_enabled = (bool)
($config->TANDEMPLUGIN_GENDER_SEARCH_ENABLED ?
$config->TANDEMPLUGIN_GENDER_SEARCH_ENABLED : false);
$this->delete_old_period = (int)
($config->TANDEMPLUGIN_DELETE_OLD_PERIOD ?
$config->TANDEMPLUGIN_DELETE_OLD_PERIOD : 6);
$this->use_tools_navigation = (int) (
$config->TANDEMPLUGIN_USE_TOOLS_NAVIGATION
? $config->TANDEMPLUGIN_USE_TOOLS_NAVIGATION
: 0
);
$this->management_email_address =
$config->TANDEMPLUGIN_MANAGEMENT_EMAIL_ADDRESS
?: '';
$this->use_level = $config->TANDEMPLUGIN_USE_LEVEL ?: '';
}
}
public function languages_action()
{
if(Navigation::hasItem($this->admin_nav_path . '/languages')) {
Navigation::activateItem($this->admin_nav_path . '/languages');
}
if(Navigation::hasItem('/profile/tandem_administration/languages')) {
Navigation::activateItem('/profile/tandem_administration/languages');
}
$sidebar = Sidebar::Get();
$actions = new ActionsWidget();
$actions->addLink(
dgettext('TandemPlugin', 'Sprache hinzufügen'),
$this->url_for('admin/add_language'),
Icon::create('add'),
['data-dialog' => 'reload-on-close']
);
$sidebar->addWidget($actions);
$this->languages = TandemLanguage::findAll();
}
protected function validateFormFields() :bool
{
$name = Request::get('name');
$name_ger = Request::get('name_ger');
$name_eng = Request::get('name_eng');
if (!$name) {
PageLayout::postError(
dgettext('TandemPlugin', 'Es wurde kein Name angegeben.')
);
return false;
}
if (!$name_ger) {
PageLayout::postError(
dgettext('TandemPlugin', 'Es wurde kein deutscher Name angegeben.')
);
return false;
}
if (!$name_eng) {
PageLayout::postError(
dgettext('TandemPlugin', 'Es wurde kein englischer Name angegeben.')
);
return false;
}
return true;
}
public function add_language_action()
{
$this->lang_id = '';
$this->name = '';
$this->name_ger = '';
$this->name_eng = '';
if (Request::submitted('save')) {
CSRFProtection::verifyUnsafeRequest();
$this->lang_id = Request::get('lang_id');
$this->name = Request::get('name');
$this->name_ger = Request::get('name_ger');
$this->name_eng = Request::get('name_eng');
$language = new TandemLanguage($this->lang_id);
if (!$language->isNew()) {
PageLayout::postError(
dgettext('TandemPlugin', 'Eine Sprache mit diesem ISO-Code existiert bereits!')
);
return;
}
if (!$this->validateFormFields()) {
return;
}
$language->name = $this->name;
$language->name_ger = $this->name_ger;
$language->name_eng = $this->name_eng;
if ($language->store()) {
PageLayout::postSuccess(
dgettext('TandemPlugin', 'Die Sprache wurde hinzugefügt.')
);
$this->response->add_header('X-Dialog-Close', '1');
} else {
PageLayout::postError(
dgettext('TandemPlugin', 'Die Sprache konnte nicht hinzugefügt werden.')
);
}
}
}
public function edit_language_action($lang_id)
{
$this->language = TandemLanguage::find($lang_id);
if (!$this->language) {
PageLayout::postError(
sprintf(
dgettext('TandemPlugin', 'Die Sprache mit dem Sprachcode %s existiert nicht.'),
$lang_id
)
);
return;
}
if (Request::submitted('save')) {
CSRFProtection::verifyUnsafeRequest();
$this->language->name = Request::get('name');
$this->language->name_ger = Request::get('name_ger');
$this->language->name_eng = Request::get('name_eng');
if (!$this->validateFormFields()) {
return;
}
$success = false;
if ($this->language->isDirty()) {
$success = $this->language->store();
} else {
$success = true;
}
if ($success) {
PageLayout::postSuccess(dgettext('TandemPlugin', 'Die Sprache wurde gespeichert.'));
$this->response->add_header('X-Dialog-Close', '1');
} else {
PageLayout::postError(dgettext('TandemPlugin', 'Die Sprache konnte nicht gespeichert werden.'));
}
}
}
public function delete_language_action($lang_id)
{
$this->language = TandemLanguage::find($lang_id);
if (!$this->language) {
PageLayout::postError(
sprintf(
dgettext('TandemPlugin', 'Die Sprache mit dem Sprachcode %s existiert nicht.'),
$lang_id
)
);
return;
}
if (Request::submitted('delete')) {
CSRFProtection::verifyUnsafeRequest();
if ($this->language->delete()) {
PageLayout::postSuccess(
dgettext('TandemPlugin', 'Die Sprache wurde gelöscht.')
);
$this->response->add_header('X-Dialog-Close', '1');
} else {
PageLayout::postError(
dgettext('TandemPlugin', 'Die Sprache konnte nicht gelöscht werden.')
);
}
}
}
public function blocklist_action()
{
if(Navigation::hasItem($this->admin_nav_path . '/blocklist')) {
Navigation::activateItem($this->admin_nav_path . '/blocklist');
}
$sidebar = Sidebar::get();
$actions = new ActionsWidget();
$actions->addLink(
dgettext('TandemPlugin', 'Eintrag hinzufügen'),
$this->url_for('admin/add_to_blocklist'),
Icon::create('add'),
['data-dialog' => '']
);
$sidebar->addWidget($actions);
$this->blocklist_entries = \TandemPlugin\BlocklistEntry::findBySQL(
"INNER JOIN `auth_user_md5` USING (`user_id`)
ORDER BY `auth_user_md5`.`Nachname` ASC, `auth_user_md5`.`Vorname` ASC"
);
}
public function add_to_blocklist_action()
{
$this->user_search = new QuickSearch('user_id', new StandardSearch('user_id'));
$this->user_id = '';
$this->reason = '';
if (Request::isPost()) {
CSRFProtection::verifyUnsafeRequest();
$this->user_id = Request::get('user_id');
$this->reason = Request::get('reason');
$user = null;
if ($this->user_id) {
$user = User::find($this->user_id);
}
if (!$user) {
PageLayout::postError(dgettext('TandemPlugin', 'Es wurde keine Person angegeben!'));
return;
}
$this->user_search->defaultValue($user->id, $user->getFullName('full_rev'));
$exists = \TandemPlugin\BlocklistEntry::countByUser_id($user->id) > 0;
if ($exists) {
PageLayout::postInfo(
sprintf(
dgettext('TandemPlugin', '%s ist bereits auf der Blockliste.'),
$user->getFullName()
)
);
return;
}
$entry = new \TandemPlugin\BlocklistEntry();
$entry->user_id = $user->id;
$entry->reason = $this->reason ?? '';
if ($entry->store()) {
PageLayout::postSuccess(
sprintf(
dgettext('TandemPlugin', '%s wurde zur Blockliste hinzugefügt.'),
$user->getFullName()
)
);
$this->response->add_header('X-Dialog-Close', '1');
} else {
PageLayout::postError(
sprintf(
dgettext('TandemPlugin', 'Beim Hinzufügen von %s zur Blockliste trat ein Fehler auf.'),
$user->getFullName()
)
);
}
}
}
public function delete_from_blocklist_action($user_id)
{
CSRFProtection::verifyUnsafeRequest();
$deleted_c = \TandemPlugin\BlocklistEntry::deleteByUser_id($user_id);
if ($deleted_c > 0) {
PageLayout::postSuccess(
dgettext('TandemPlugin', 'Die Person wurde von der Blockliste entfernt.')
);
} elseif ($deleted_c === 0) {
PageLayout::postWarning(
dgettext('TandemPlugin', 'Es gab keinen Eintrag auf der Blockliste für die gewählte Person.')
);
}
$this->redirect('admin/blocklist');
}
}