aboutsummaryrefslogtreecommitdiff
path: root/lib/admission.inc.php
blob: d0728f9d924f86fc9267386c8263d803a3366774 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
<?
# Lifter002: TODO
# Lifter003: TEST
# Lifter007: TODO
# Lifter010: TODO
/**
 * admission.inc.php
 *
 * the basic library for the admisson system
 *
 *
 * @author       Cornelis Kater <ckater@gwdg.de>, Suchi & Berg GmbH <info@data-quest.de>
 * @access       public
 * @modulegroup      admission
 * @module       admission.inc.php
 * @package      studip_core
 * @deprecated since Stud.IP 5.3
 *
 */

// +---------------------------------------------------------------------------+
// This file is part of Stud.IP
// admission.inc.php
// Funktionen die zur Teilnehmerbeschraenkung benoetigt werden
// Copyright (C) 2002 Cornelis Kater <ckater@gwdg.de>, Suchi & Berg GmbH <info@data-quest.de>
// +---------------------------------------------------------------------------+
// 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 any later version.
// +---------------------------------------------------------------------------+
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
// +---------------------------------------------------------------------------+


require_once 'lib/messaging.inc.php';
require_once 'lib/dates.inc.php';

/**
 * Insert a user into a seminar with optional log-message and contingent
 *
 * @param string   $seminar_id
 * @param string   $user_id
 * @param string   $status       status of user in the seminar (user, autor, tutor, dozent)
 * @param boolean  $copy_studycourse  if true, the studycourse is copied from admission_seminar_user
 *                                    to seminar_user. Overrides the $contingent-parameter
 * @param string   $contingent   optional studiengang_id, if no id is given, no contingent is considered
 * @param string   $log_message  optional log-message. if no log-message is given a default one is used
 * @return bool
 */
function insert_seminar_user($seminar_id, $user_id, $status, $copy_studycourse = false, $contingent = false, $log_message = false) {

    if (!$user_id) {
        return false;
    }
    // get the seminar-object
    $sem = Seminar::GetInstance($seminar_id);

    $admission_status = '';
    $admission_comment = '';
    $mkdate = time();

    $stmt = DBManager::get()->prepare("SELECT * FROM admission_seminar_user
            WHERE seminar_id = ? AND user_id = ?");
    $stmt->execute([$seminar_id, $user_id]);
    if ($data = $stmt->fetch(PDO::FETCH_ASSOC)) {
        // copy the studycourse from admission_seminar_user
        if ($copy_studycourse && $data['studiengang_id']) {
            $contingent = $data['studiengang_id'];
        }
        $admission_status = $data['status'];
        $admission_comment = ($data['comment'] == NULL) ? '' : $data['comment'];
        $mkdate = $data['mkdate'];
    }

    // check if there are places left in the submitted contingent (if any)
    //ignore if preliminary
    if ($admission_status != 'accepted' && $contingent && $sem->isAdmissionEnabled() && !$sem->getFreeAdmissionSeats($contingent)) {
        return false;
    }

    // get coloured group as used on meine_seminare
    $colour_group = $sem->getDefaultGroup();

    // LOGGING
    // if no log message is submitted use a default one
    if (!$log_message) {
        $log_message = 'Wurde in die Veranstaltung eingetragen, admission_status: '. $admission_status . ' Kontingent: ' . $contingent;
    }
    StudipLog::log('SEM_USER_ADD', $seminar_id, $user_id, $status, $log_message);
    // actually insert the user into the seminar
    $stmt = DBManager::get()->prepare('INSERT IGNORE INTO seminar_user
        (Seminar_id, user_id, status, comment, gruppe, mkdate)
        VALUES (?, ?, ?, ?, ?, ?)');
    $stmt->execute([$seminar_id, $user_id, $status, $admission_comment, $colour_group, $mkdate]);

    NotificationCenter::postNotification('UserDidEnterCourse', $seminar_id, $user_id);

    if ($admission_status) {
        // delete the entries, user is now in the seminar
        $stmt = DBManager::get()->prepare('DELETE FROM admission_seminar_user
            WHERE user_id = ? AND seminar_id = ?');
        $stmt->execute([$user_id, $seminar_id]);

        //renumber the waiting/accepted/lot list, a user was deleted from it
        renumber_admission($seminar_id);
    }
    $cs = $sem->getCourseSet();
    if ($cs) {
        $prio_delete = AdmissionPriority::unsetPriority($cs->getId(), $user_id, $sem->getId());
    }

    CalendarScheduleModel::deleteSeminarEntries($user_id, $seminar_id);

    // reload the seminar, the contingents have changed
    $sem->restore();

    // Check if a parent course exists and insert user there.
    if ($sem->parent_course) {
        insert_seminar_user($sem->parent_course, $user_id, $status, $copy_studycourse, $contingent, $log_message);
    }

    return true;
}


/**
 * This function numbers a waiting list
 *
 * Use this functions, if a person was moved from the waiting list or there were other changes
 * to the waiting list. The User gets a message, if the parameter is set and the position
 * on the waiting  list has changed.
 *
 * @param        string  seminar_id      the seminar_id of the seminar to calculate
 * @param        boolean send_message        should a system-message be send?
 *
 */

function renumber_admission ($seminar_id, $send_message = TRUE)
{
    $messaging = new messaging;

    $seminar = Seminar::GetInstance($seminar_id);
    if ($seminar->isAdmissionEnabled()) {
        //Liste einlesen
        $query = "SELECT user_id
                  FROM admission_seminar_user
                  WHERE seminar_id = ? AND status = 'awaiting'
                  ORDER BY position";
        $statement = DBManager::get()->prepare($query);
        $statement->execute([$seminar->id]);
        $user_ids = $statement->fetchAll(PDO::FETCH_COLUMN);

        // Prepare statement that updates the position
        $query = "UPDATE admission_seminar_user
                  SET position = ?
                  WHERE user_id = ? AND seminar_id = ?";
        $update_statement = DBManager::get()->prepare($query);

        $position = 1;
        //Liste neu numerieren
        foreach ($user_ids as $user_id) {
            $update_statement->execute([$position, $user_id, $seminar->id]);

            //User benachrichten
            if ($update_statement->rowCount() && Config::get()->NOTIFY_ON_WAITLIST_ADVANCE && $send_message) {
                //Usernamen auslesen
                $username = get_username($user_id);

                setTempLanguage($user_id);
                $message = sprintf(_('Sie sind in der Warteliste der Veranstaltung **%s (%s)** hochgestuft worden. Sie stehen zur Zeit auf Position %s.'),
                    $seminar->name,
                    $seminar->getFormattedTurnus(),
                    $position);
                $subject = sprintf(_('Ihre Position auf der Warteliste der Veranstaltung %s wurde verändert'), $seminar->name);
                restoreLanguage();

                $messaging->insert_message($message, $username, '____%system%____', FALSE, FALSE, '1', FALSE, $subject);
            }
            $position += 1;
        }
    }
}


/*
 * This function is a kind of wrapper, so that no nasty loops between the updaters occur
 *
 **/
function update_admission ($seminar_id, $send_message = TRUE) {
    if(Seminar::GetInstance($seminar_id, TRUE)->isAdmissionEnabled()){
        normal_update_admission($seminar_id, $send_message);
    }
}

/**
 * This function updates an admission procedure
 *
 * The function checks, if user could be insert to the seminar.
 * The User gets a message, if he is inserted to the seminar
 *
 * @param        string  seminar_id      the seminar_id of the seminar to calculate
 * @param        boolean send_message        should a system-message be send?
 *
 */
function normal_update_admission($seminar_id, $send_message = TRUE)
{
    $messaging=new messaging;

    //Daten holen / Abfrage ob ueberhaupt begrenzt
    $seminar = Seminar::GetInstance($seminar_id);

    if($seminar->isAdmissionEnabled()){

        $sem_preliminary = ($seminar->admission_prelim == 1);
        $cs = $seminar->getCourseSet();
        //Veranstaltung einfach auffuellen (nach Lostermin und Ende der Kontingentierung)
        if (!$seminar->admission_disable_waitlist_move && $cs->hasAlgorithmRun()) {
            //anzahl der freien Plaetze holen
            $count = (int)$seminar->getFreeAdmissionSeats();

            //Studis auswaehlen, die jetzt aufsteigen koennen
            $query = "SELECT user_id, username
                      FROM admission_seminar_user
                      LEFT JOIN auth_user_md5 USING (user_id)
                      WHERE seminar_id = ? AND status = 'awaiting'
                      ORDER BY position
                      LIMIT " . (int)$count;
            $statement = DBManager::get()->prepare($query);
            $statement->execute([$seminar->getId()]);
            $temp = $statement->fetchAll(PDO::FETCH_ASSOC);

            foreach ($temp as $row) {
                //ok, here ist the "colored-group" meant (for grouping on meine_seminare), not the grouped seminars as above!
                $group = select_group($seminar->getSemesterStartTime());

                if (!$sem_preliminary) {
                    $query = "INSERT INTO seminar_user
                                (user_id, Seminar_id, status, gruppe, mkdate)
                              VALUES (?, ?, 'autor', ?, UNIX_TIMESTAMP())";
                    $statement = DBManager::get()->prepare($query);
                    $statement->execute([
                        $row['user_id'],
                        $seminar->getId(),
                        $group
                    ]);
                    $affected = $statement->rowCount();

                    NotificationCenter::postNotification('UserDidEnterCourse', $seminar->getId(), $row['user_id']);
                } else {
                    $query = "UPDATE admission_seminar_user
                              SET status = 'accepted'
                              WHERE user_id = ? AND seminar_id = ?";
                    $statement = DBManager::get()->prepare($query);
                    $statement->execute([
                        $row['user_id'],
                        $seminar->getId()
                    ]);
                    $affected = $statement->rowCount();
                }
                if ($affected > 0) {
                    $log_message = 'Wurde automatisch aus der Warteliste in die Veranstaltung eingetragen.';
                    StudipLog::log('SEM_USER_ADD', $seminar->getId(), $row['user_id'], $sem_preliminary ? 'accepted' : 'autor', $log_message);
                    if (!$sem_preliminary) {
                        $query = "DELETE FROM admission_seminar_user
                                  WHERE user_id = ? AND seminar_id = ?";
                        $statement = DBManager::get()->prepare($query);
                        $statement->execute([
                            $row['user_id'],
                            $seminar->getId()
                        ]);
                        $affected = $statement->rowCount();
                    } else {
                        $affected = 0;
                    }
                    //User benachrichtigen
                    if (($sem_preliminary || $affected > 0) && $send_message) {
                        setTempLanguage($row['user_id']);
                        if (!$sem_preliminary) {
                            $message = sprintf (_('Sie sind in die Veranstaltung **%s (%s)** eingetragen worden, da für Sie ein Platz frei geworden ist. Damit sind Sie für die Teilnahme an der Veranstaltung zugelassen. Ab sofort finden Sie die Veranstaltung in der Übersicht Ihrer Veranstaltungen.'), $seminar->getName(), $seminar->getFormattedTurnus(true));
                        } else {
                            $message = sprintf (_('Sie haben den Status vorläufig akzeptiert in der Veranstaltung **%s (%s)** erhalten, da für Sie ein Platz freigeworden ist.'), $seminar->getName(), $seminar->getFormattedTurnus(true));
                        }
                        $subject = sprintf(_("Teilnahme an der Veranstaltung %s"),$seminar->getName());
                        restoreLanguage();

                        $messaging->insert_message($message, $row['username'], '____%system%____', FALSE, FALSE, '1', FALSE, $subject, true);
                    }
                }
            }
            //Warteposition der restlichen User neu eintragen
            renumber_admission($seminar_id, FALSE);
        }
        $seminar->restore();
    }
}



/**
 * sets a user on a waiting list for a registration procedure
 *
 * if applicable ($status == 'awaiting') returns the position
 *
 * @param        string  user_id
 * @param        string  seminar_id
 * @param        string  status              'claiming','awaiting','accepted'
 * @param        string  studiengang_id
 * @param        string  comment
 * @return       integer position on waiting list
 *
 */
function admission_seminar_user_insert($user_id, $seminar_id, $status, $studiengang_id = '', $comment = '')
{
    if ($status == 'accepted') {
        $query = "INSERT INTO admission_seminar_user
                    (user_id, seminar_id, status, mkdate, comment)
                  VALUES (?, ?, ?, UNIX_TIMESTAMP(), ?)";
        $statement = DBManager::get()->prepare($query);
        $statement->execute([
            $user_id,
            $seminar_id,
            $status,
            $comment
        ]);
        return $statement->rowCount();
    } elseif ($status == 'awaiting') {
        $query = "INSERT INTO admission_seminar_user
                    (user_id, seminar_id, status, mkdate, comment, position)
                  SELECT ?, ?, 'awaiting', UNIX_TIMESTAMP(), ?, IFNULL(MAX(position), 0) + 1
                  FROM admission_seminar_user
                  WHERE seminar_id = ? AND status != 'accepted'";
        $statement = DBManager::get()->prepare($query);
        $statement->execute([
            $user_id,
            $seminar_id,
            $comment,
            $seminar_id
        ]);
    }
    return admission_seminar_user_get_position($user_id, $seminar_id);
}

/**
 * returns the position for a user on a waiting list
 *
 * if the user is not found false is returned, return true if the user is found but
 * no position is available
 *
 * @param        string  user_id
 * @param        string  seminar_id
 * @return       integer position in waiting list or false if not found
 *
 */
function admission_seminar_user_get_position($user_id, $seminar_id)
{
    $query = "SELECT IFNULL(position, 'na')
              FROM admission_seminar_user
              WHERE user_id = ? AND seminar_id = ? AND status='awaiting'";
    $statement = DBManager::get()->prepare($query);
    $statement->execute([$user_id, $seminar_id]);
    $position = $statement->fetchColumn();

    return $position == 'na' ? true : $position;
}