269f5a2b5baf5559a0f7504a6d9d647701546390
[platal.git] / modules / xnetevents.php
1 <?php
2 /***************************************************************************
3 * Copyright (C) 2003-2007 Polytechnique.org *
4 * http://opensource.polytechnique.org/ *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 ***************************************************************************/
21
22 define('NB_PER_PAGE', 25);
23
24 class XnetEventsModule extends PLModule
25 {
26 function handlers()
27 {
28 return array(
29 '%grp/events' => $this->make_hook('events', AUTH_MDP),
30 '%grp/events/sub' => $this->make_hook('sub', AUTH_MDP),
31 '%grp/events/csv' => $this->make_hook('csv', AUTH_MDP),
32 '%grp/events/ical' => $this->make_hook('ical', AUTH_MDP),
33 '%grp/events/edit' => $this->make_hook('edit', AUTH_MDP),
34 '%grp/events/admin' => $this->make_hook('admin', AUTH_MDP),
35 );
36 }
37
38 function handler_events(&$page, $archive = null)
39 {
40 global $globals;
41
42 if ($archive == 'archive') {
43 $archive = true;
44 new_groupadmin_page('xnetevents/index.tpl');
45 } else {
46 $archive = false;
47 new_group_open_page('xnetevents/index.tpl');
48 }
49
50 $action = null;
51 if (Post::has('del')) {
52 $action = 'del';
53 $eid = Post::v('del');
54 } elseif (Post::has('archive')) {
55 $action = 'archive';
56 $eid = Post::v('archive');
57 } elseif (Post::has('unarchive')) {
58 $action = 'unarchive';
59 $eid = Post::v('unarchive');
60 }
61
62 if (!is_null($action)) {
63 if (!may_update()) {
64 return PL_FORBIDDEN;
65 }
66
67 $res = XDB::query("SELECT asso_id, short_name FROM groupex.evenements
68 WHERE eid = {?} AND asso_id = {?}",
69 $eid, $globals->asso('id'));
70
71 $tmp = $res->fetchOneRow();
72 if (!$tmp) {
73 return PL_FORBIDDEN;
74 }
75 }
76
77 if ($action == 'del') {
78 // deletes the event mailing aliases
79 if ($tmp[1]) {
80 XDB::execute(
81 "DELETE FROM virtual WHERE type = 'evt' AND alias LIKE {?}",
82 $tmp[1].'-absents@%');
83 XDB::execute(
84 "DELETE FROM virtual WHERE type = 'evt' AND alias LIKE {?}",
85 $tmp[1].'-participants@%');
86 }
87
88 // deletes the event items
89 XDB::execute("DELETE FROM groupex.evenements_items WHERE eid = {?}", $eid);
90
91 // deletes the event participants
92 XDB::execute("DELETE FROM groupex.evenements_participants
93 WHERE eid = {?}", $eid);
94
95 // deletes the event
96 XDB::execute("DELETE FROM groupex.evenements
97 WHERE eid = {?} AND asso_id = {?}",
98 $eid, $globals->asso('id'));
99
100 // delete the requests for payments
101 require_once 'validations.inc.php';
102 XDB::execute("DELETE FROM requests
103 WHERE type = 'paiements' AND data LIKE {?}",
104 PayReq::same_event($eid, $globals->asso('id')));
105 }
106
107 if ($action == 'archive') {
108 XDB::execute("UPDATE groupex.evenements
109 SET archive = 1
110 WHERE eid = {?} AND asso_id = {?}",
111 $eid, $globals->asso('id'));
112 }
113
114 if ($action == 'unarchive') {
115 XDB::execute("UPDATE groupex.evenements
116 SET archive = 0
117 WHERE eid = {?} AND asso_id = {?}",
118 $eid, $globals->asso('id'));
119 }
120
121 $page->assign('archive', $archive);
122 $evenements = XDB::iterator(
123 "SELECT e.*, LEFT(10, e.debut) AS debut_day, LEFT(10, e.fin) AS fin_day,
124 IF(e.deadline_inscription, e.deadline_inscription >= LEFT(NOW(), 10),
125 1) AS inscr_open, e.deadline_inscription,
126 u.nom, u.prenom, u.promo, a.alias,
127 MAX(ep.nb) IS NOT NULL AS inscrit, MAX(ep.paid) AS paid
128 FROM groupex.evenements AS e
129 INNER JOIN x4dat.auth_user_md5 AS u ON u.user_id = e.organisateur_uid
130 INNER JOIN x4dat.aliases AS a ON (a.type = 'a_vie' AND a.id = u.user_id)
131 LEFT JOIN groupex.evenements_participants AS ep ON (ep.eid = e.eid AND ep.uid = {?})
132 WHERE asso_id = {?}
133 AND archive = " . ($archive ? "1 " : "0 ")
134 . (is_member() || may_update() ? "" : " AND accept_nonmembre != 0 ")
135 . "GROUP BY e.eid
136 ORDER BY inscr_open DESC, debut DESC", S::v('uid'), $globals->asso('id'));
137
138 $evts = array();
139
140 while ($e = $evenements->next()) {
141 $e['show_participants'] = ($e['show_participants'] && (is_member() || may_update()));
142 $res = XDB::query(
143 "SELECT titre, details, montant, ei.item_id, nb, ep.paid
144 FROM groupex.evenements_items AS ei
145 LEFT JOIN groupex.evenements_participants AS ep
146 ON (ep.eid = ei.eid AND ep.item_id = ei.item_id AND uid = {?})
147 WHERE ei.eid = {?}",
148 S::v('uid'), $e['eid']);
149 $e['moments'] = $res->fetchAllAssoc();
150
151 $e['topay'] = 0;
152 $e['paid'] = $e['moments'][0]['paid'];
153 foreach ($e['moments'] as $m) {
154 $e['topay'] += $m['nb'] * $m['montant'];
155 }
156
157 $query = XDB::query(
158 "SELECT montant
159 FROM {$globals->money->mpay_tprefix}transactions AS t
160 WHERE ref = {?} AND uid = {?}", $e['paiement_id'], S::v('uid'));
161 $montants = $query->fetchColumn();
162
163 foreach ($montants as $m) {
164 $p = strtr(substr($m, 0, strpos($m, 'EUR')), ',', '.');
165 $e['paid'] += trim($p);
166 }
167
168 if (Env::has('updated') && $e['eid'] == Env::i('updated')) {
169 $page->assign('updated', $e);
170 }
171 $evts[] = $e;
172 }
173
174 $page->assign('evenements', $evts);
175 }
176
177 function handler_sub(&$page, $eid = null)
178 {
179 require_once dirname(__FILE__).'/xnetevents/xnetevents.inc.php';
180
181 new_group_open_page('xnetevents/subscribe.tpl');
182
183 $evt = get_event_detail($eid);
184 if (!$evt) {
185 return PL_NOT_FOUND;
186 }
187
188 if (!$evt['inscr_open']) {
189 $page->kill('Les inscriptions pour cet événement sont closes');
190 }
191 if (!$evt['accept_nonmembre'] && !is_member() && !may_update()) {
192 $page->kill('Cet événement est fermé aux non-membres du groupe');
193 }
194
195 $page->assign('event', $evt);
196
197 if (!Post::has('submit')) {
198 return;
199 }
200
201 $moments = Post::v('moment', array());
202 $pers = Post::v('personnes', array());
203 $subs = array();
204
205 foreach ($moments as $j => $v) {
206 $subs[$j] = intval($v);
207
208 // retreive ohter field when more than one person
209 if ($subs[$j] == 2) {
210 if (!isset($pers[$j]) || !is_numeric($pers[$j])
211 || $pers[$j] < 0)
212 {
213 $page->trig('Tu dois choisir un nombre d\'invités correct !');
214 return;
215 }
216 $subs[$j] = 1 + $pers[$j];
217 }
218 }
219
220 // impossible to unsubscribe if you already paid sthing
221 if (!array_sum($subs) && $evt['paid'] != 0) {
222 $page->trig("Impossible de te désinscrire complètement ".
223 "parce que tu as fait un paiement par ".
224 "chèque ou par liquide. Contacte un ".
225 "administrateur du groupe si tu es sûr de ".
226 "ne pas venir");
227 return;
228 }
229
230 // update actual inscriptions
231 $updated = false;
232 $total = 0;
233 $paid = $evt['paid'] ? $evt['paid'] : 0;
234 foreach ($subs as $j => $nb) {
235 if ($nb >= 0) {
236 XDB::execute(
237 "REPLACE INTO groupex.evenements_participants
238 VALUES ({?}, {?}, {?}, {?}, {?})",
239 $eid, S::v('uid'), $j, $nb, $paid);
240 $updated = $eid;
241 } else {
242 XDB::execute(
243 "DELETE FROM groupex.evenements_participants
244 WHERE eid = {?} AND uid = {?} AND item_id = {?}",
245 $eid, S::v("uid"), $j);
246 $updated = $eid;
247 }
248 $total += $nb;
249 }
250 if ($updated !== false) {
251 subscribe_lists_event($total, S::i('uid'), $evt);
252 }
253 $page->assign('event', get_event_detail($eid));
254 }
255
256 function handler_csv(&$page, $eid = null, $item_id = null)
257 {
258 require_once dirname(__FILE__).'/xnetevents/xnetevents.inc.php';
259
260 if (!is_numeric($item_id)) {
261 $item_id = null;
262 }
263
264 $evt = get_event_detail($eid, $item_id);
265 if (!$evt) {
266 return PL_NOT_FOUND;
267 }
268
269 header('Content-type: text/x-csv; encoding=iso-8859-1');
270 header('Pragma: ');
271 header('Cache-Control: ');
272
273 $page->changeTpl('xnetevents/csv.tpl', NO_SKIN);
274
275 $admin = may_update();
276
277 $tri = (Env::v('order') == 'alpha' ? 'promo, nom, prenom' : 'nom, prenom, promo');
278
279 $page->assign('participants',
280 get_event_participants($evt, $item_id, $tri));
281
282 $page->assign('admin', $admin);
283 $page->assign('moments', $evt['moments']);
284 $page->assign('money', $evt['money']);
285 $page->assign('tout', !Env::v('item_id', false));
286 }
287
288 function handler_ical(&$page, $eid = null)
289 {
290 global $globals;
291
292 require_once dirname(__FILE__).'/xnetevents/xnetevents.inc.php';
293 $evt = get_event_detail($eid);
294 if (!$evt) {
295 return PL_FORBIDDEN;
296 }
297 $evt['debut'] = preg_replace('/(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/', "\\1\\2\\3T\\4\\5\\6", $evt['debut']);
298 $evt['fin'] = preg_replace('/(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/', "\\1\\2\\3T\\4\\5\\6", $evt['fin']);
299
300 foreach ($evt['moments'] as $m) {
301 $evt['descriptif'] .= "\n\n** " . $m['titre'] . " **\n" . $m['details'];
302 }
303
304 $page->changeTpl('xnetevents/calendar.tpl', NO_SKIN);
305
306 require_once('ical.inc.php');
307 $page->assign('asso', $globals->asso());
308 $page->assign('timestamp', time());
309 $page->assign('admin', may_update());
310
311 if (may_update()) {
312 $page->assign('participants', get_event_participants($evt, null, 'promo, nom, prenom'));
313 }
314 $page->register_function('display_ical', 'display_ical');
315 $page->assign_by_ref('e', $evt);
316
317 header('Content-Type: text/calendar; charset=utf-8');
318 }
319
320 function handler_edit(&$page, $eid = null)
321 {
322 global $globals;
323
324 // get eid if the the given one is a short name
325 if (!is_null($eid) && !is_numeric($eid)) {
326 $res = XDB::query("SELECT eid
327 FROM groupex.evenements
328 WHERE asso_id = {?} AND short_name = {?}",
329 $globals->asso('id'), $eid);
330 if ($res->numRows()) {
331 $eid = (int)$res->fetchOneCell();
332 }
333 }
334
335 // check the event is in our group
336 if (!is_null($eid)) {
337 $res = XDB::query("SELECT short_name
338 FROM groupex.evenements
339 WHERE eid = {?} AND asso_id = {?}",
340 $eid, $globals->asso('id'));
341 if ($res->numRows()) {
342 $infos = $res->fetchOneAssoc();
343 } else {
344 return PL_FORBIDDEN;
345 }
346 }
347
348 new_groupadmin_page('xnetevents/edit.tpl');
349
350 $moments = range(1, 4);
351 $error = false;
352 $page->assign('moments', $moments);
353
354 if (Post::v('intitule')) {
355 require_once dirname(__FILE__).'/xnetevents/xnetevents.inc.php';
356 $short_name = event_change_shortname($page, $infos['short_name'],
357 Env::v('short_name', ''));
358 if ($short_name != Env::v('short_name')) {
359 $error = true;
360 }
361 $evt = array(
362 'eid' => $eid,
363 'asso_id' => $globals->asso('id'),
364 'paiement_id' => Post::v('paiement_id') > 0 ? Post::v('paiement_id') : null,
365 'debut' => Post::v('deb_Year').'-'.Post::v('deb_Month')
366 .'-'.Post::v('deb_Day').' '.Post::v('deb_Hour')
367 .':'.Post::v('deb_Minute').':00',
368 'fin' => Post::v('fin_Year').'-'.Post::v('fin_Month')
369 .'-'.Post::v('fin_Day').' '.Post::v('fin_Hour')
370 .':'.Post::v('fin_Minute').':00',
371 'short_name' => $short_name,
372 );
373
374 $trivial = array('intitule', 'descriptif', 'noinvite',
375 'show_participants', 'accept_nonmembre', 'organisateur_uid');
376 foreach ($trivial as $k) {
377 $evt[$k] = Post::v($k);
378 }
379 if (!$eid) {
380 $evt['organisateur_uid'] = S::v('uid');
381 }
382
383 if (Post::v('deadline')) {
384 $evt['deadline_inscription'] = Post::v('inscr_Year').'-'
385 . Post::v('inscr_Month').'-'
386 . Post::v('inscr_Day');
387 } else {
388 $evt['deadline_inscription'] = null;
389 }
390
391 // Store the modifications in the database
392 XDB::execute('REPLACE INTO groupex.evenements
393 SET eid={?}, asso_id={?}, organisateur_uid={?}, intitule={?},
394 paiement_id = {?}, descriptif = {?}, debut = {?},
395 fin = {?}, show_participants = {?}, short_name = {?},
396 deadline_inscription = {?}, noinvite = {?},
397 accept_nonmembre = {?}',
398 $evt['eid'], $evt['asso_id'], $evt['organisateur_uid'],
399 $evt['intitule'], $evt['paiement_id'], $evt['descriptif'],
400 $evt['debut'], $evt['fin'], $evt['show_participants'],
401 $evt['short_name'], $evt['deadline_inscription'],
402 $evt['noinvite'], $evt['accept_nonmembre']);
403
404 // if new event, get its id
405 if (!$eid) {
406 $eid = XDB::insertId();
407 }
408
409 $nb_moments = 0;
410 $money_defaut = 0;
411
412 foreach ($moments as $i) {
413 if (Post::v('titre'.$i)) {
414 $nb_moments++;
415
416 $montant = strtr(Post::v('montant'.$i), ',', '.');
417 $money_defaut += (float)$montant;
418 XDB::execute("
419 REPLACE INTO groupex.evenements_items
420 VALUES ({?}, {?}, {?}, {?}, {?})",
421 $eid, $i, Post::v('titre'.$i),
422 Post::v('details'.$i), $montant);
423 } else {
424 XDB::execute("DELETE FROM groupex.evenements_items
425 WHERE eid = {?} AND item_id = {?}", $eid, $i);
426 }
427 }
428 // request for a new payment
429 if (Post::v('paiement_id') == -1 && $money_defaut >= 0) {
430 require_once 'validations.inc.php';
431 $p = new PayReq(S::v('uid'),
432 Post::v('intitule')." - ".$globals->asso('nom'),
433 Post::v('site'), $money_defaut,
434 Post::v('confirmation'), 0, 999,
435 $globals->asso('id'), $eid);
436 $p->submit();
437 }
438
439 // events with no sub-event: add a sub-event with no name
440 if ($nb_moments == 0) {
441 XDB::execute("INSERT INTO groupex.evenements_items
442 VALUES ({?}, {?}, '', '', 0)", $eid, 1);
443 }
444
445 if (!$error) {
446 pl_redirect('events');
447 }
448 }
449
450 // get a list of all the payment for this asso
451 $res = XDB::iterator("SELECT id, text
452 FROM {$globals->money->mpay_tprefix}paiements
453 WHERE asso_id = {?}", $globals->asso('id'));
454 $paiements = array();
455 while ($a = $res->next()) $paiements[$a['id']] = $a['text']; {
456 $page->assign('paiements', $paiements);
457 }
458
459 // when modifying an old event retreive the old datas
460 if ($eid) {
461 $res = XDB::query(
462 "SELECT eid, intitule, descriptif, debut, fin, organisateur_uid,
463 show_participants, paiement_id, short_name,
464 deadline_inscription, noinvite, accept_nonmembre
465 FROM groupex.evenements
466 WHERE eid = {?}", $eid);
467 $evt = $res->fetchOneAssoc();
468 // find out if there is already a request for a payment for this event
469 require_once 'validations.inc.php';
470 $res = XDB::query("SELECT stamp FROM requests
471 WHERE type = 'paiements' AND data LIKE {?}",
472 PayReq::same_event($eid, $globals->asso('id')));
473 $stamp = $res->fetchOneCell();
474 if ($stamp) {
475 $evt['paiement_id'] = -2;
476 $evt['paiement_req'] = $stamp;
477 }
478 $page->assign('evt', $evt);
479 // get all the different moments infos
480 $res = XDB::iterator(
481 "SELECT item_id, titre, details, montant
482 FROM groupex.evenements_items AS ei
483 INNER JOIN groupex.evenements AS e ON(e.eid = ei.eid)
484 WHERE e.eid = {?}
485 ORDER BY item_id", $eid);
486 $items = array();
487 while ($item = $res->next()) {
488 $items[$item['item_id']] = $item;
489 }
490 $page->assign('items', $items);
491 }
492 $page->assign('url_ref', $eid);
493 }
494
495 function handler_admin(&$page, $eid = null, $item_id = null)
496 {
497 global $globals;
498
499 require_once dirname(__FILE__).'/xnetevents/xnetevents.inc.php';
500
501 $evt = get_event_detail($eid, $item_id);
502 if (!$evt) {
503 return PL_NOT_FOUND;
504 }
505
506 if ($evt['show_participants']) {
507 new_group_page('xnetevents/admin.tpl');
508 } else {
509 new_groupadmin_page('xnetevents/admin.tpl');
510 }
511
512 if (may_update() && Post::v('adm')) {
513 $member = get_infos(Post::v('mail'));
514 if (!$member) {
515 $page->trig("Membre introuvable");
516 }
517
518 // change the price paid by a participant
519 if (Env::v('adm') == 'prix' && $member) {
520 XDB::execute("UPDATE groupex.evenements_participants
521 SET paid = IF(paid + {?} > 0, paid + {?}, 0)
522 WHERE uid = {?} AND eid = {?}",
523 strtr(Env::v('montant'), ',', '.'),
524 strtr(Env::v('montant'), ',', '.'),
525 $member['uid'], $evt['eid']);
526 }
527
528 // change the number of personns coming with a participant
529 if (Env::v('adm') == 'nbs' && $member) {
530 $res = XDB::query("SELECT paid
531 FROM groupex.evenements_participants
532 WHERE uid = {?} AND eid = {?}",
533 $member['uid'], $evt['eid']);
534
535 $paid = intval($res->fetchOneCell());
536 $nbs = Post::v('nb', array());
537
538 foreach ($nbs as $id => $nb) {
539 $nb = max(intval($nb), 0);
540 XDB::execute("REPLACE INTO groupex.evenements_participants
541 VALUES ({?}, {?}, {?}, {?}, {?})",
542 $evt['eid'], $member['uid'], $id, $nb, $paid);
543 }
544
545 $res = XDB::query("SELECT COUNT(uid) AS cnt, SUM(nb) AS nb
546 FROM groupex.evenements_participants
547 WHERE uid = {?} AND eid = {?}
548 GROUP BY uid",
549 $member['uid'], $evt['eid']);
550 $u = $res->fetchOneAssoc();
551 $u = $u['cnt'] ? null : $u['nb'];
552 subscribe_lists_event($u, $member['uid'], $evt);
553 }
554
555 $evt = get_event_detail($eid, $item_id);
556 }
557
558 $page->assign('evt', $evt);
559 $page->assign('tout', is_null($item_id));
560
561 if (count($evt['moments'])) {
562 $page->assign('moments', $evt['moments']);
563 }
564
565 $tri = (Env::v('order') == 'alpha' ? 'promo, nom, prenom' : 'nom, prenom, promo');
566 $whereitemid = is_null($item_id) ? '' : "AND ep.item_id = $item_id";
567 $res = XDB::iterRow(
568 'SELECT UPPER(SUBSTRING(IF(u.nom IS NULL, m.nom,
569 IF(u.nom_usage<>"", u.nom_usage, u.nom)), 1, 1)),
570 COUNT(DISTINCT ep.uid)
571 FROM groupex.evenements_participants AS ep
572 INNER JOIN groupex.evenements AS e ON (ep.eid = e.eid)
573 LEFT JOIN groupex.membres AS m ON ( ep.uid = m.uid AND e.asso_id = m.asso_id)
574 LEFT JOIN auth_user_md5 AS u ON ( u.user_id = ep.uid )
575 WHERE ep.eid = {?} '.$whereitemid.'
576 GROUP BY UPPER(SUBSTRING(IF(u.nom IS NULL,m.nom,u.nom), 1, 1))', $evt['eid']);
577
578 $alphabet = array();
579 $nb_tot = 0;
580 while (list($char, $nb) = $res->next()) {
581 $alphabet[ord($char)] = $char;
582 $nb_tot += $nb;
583 if (Env::has('initiale') && $char == strtoupper(Env::v('initiale'))) {
584 $tot = $nb;
585 }
586 }
587 ksort($alphabet);
588 $page->assign('alphabet', $alphabet);
589
590 $ofs = Env::i('offset');
591 $tot = Env::v('initiale') ? $tot : $nb_tot;
592 $nbp = intval(($tot-1)/NB_PER_PAGE);
593 $links = array();
594 if ($ofs) {
595 $links['précédent'] = $ofs-1;
596 }
597 for ($i = 0; $i <= $nbp; $i++) {
598 $links[(string)($i+1)] = $i;
599 }
600 if ($ofs < $nbp) {
601 $links['suivant'] = $ofs+1;
602 }
603 if (count($links)>1) {
604 $page->assign('links', $links);
605 }
606
607 if ($evt['paiement_id']) {
608 $res = XDB::iterator(
609 "SELECT IF(u.nom_usage<>'', u.nom_usage, u.nom) AS nom, u.prenom,
610 u.promo, a.alias AS email, t.montant
611 FROM {$globals->money->mpay_tprefix}transactions AS t
612 INNER JOIN auth_user_md5 AS u ON(t.uid = u.user_id)
613 INNER JOIN aliases AS a ON (a.id = t.uid AND a.type='a_vie' )
614 LEFT JOIN groupex.evenements_participants AS ep ON(ep.uid = t.uid AND ep.eid = {?})
615 WHERE t.ref = {?} AND ep.uid IS NULL",
616 $evt['eid'], $evt['paiement_id']);
617 $page->assign('oublis', $res->total());
618 $page->assign('oubliinscription', $res);
619 }
620
621 $page->assign('participants',
622 get_event_participants($evt, $item_id, $tri,
623 "LIMIT ".($ofs*NB_PER_PAGE).", ".NB_PER_PAGE));
624 }
625 }
626
627 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
628 ?>