2006 => 2007 Happy New Year\!
[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 foreach ($subs as $j => $nb) {
234 if ($nb >= 0) {
235 XDB::execute(
236 "REPLACE INTO groupex.evenements_participants
237 VALUES ({?}, {?}, {?}, {?}, {?})",
238 $eid, S::v('uid'), $j, $nb, $evt['paid']);
239 $updated = $eid;
240 } else {
241 XDB::execute(
242 "DELETE FROM groupex.evenements_participants
243 WHERE eid = {?} AND uid = {?} AND item_id = {?}",
244 $eid, S::v("uid"), $j);
245 $updated = $eid;
246 }
247 $total += $nb;
248 }
249 if ($updated !== false) {
250 subscribe_lists_event($total, S::i('uid'), $evt);
251 }
252 $page->assign('event', get_event_detail($eid));
253 }
254
255 function handler_csv(&$page, $eid = null, $item_id = null)
256 {
257 require_once dirname(__FILE__).'/xnetevents/xnetevents.inc.php';
258
259 if (!is_numeric($item_id)) {
260 $item_id = null;
261 }
262
263 $evt = get_event_detail($eid, $item_id);
264 if (!$evt) {
265 return PL_NOT_FOUND;
266 }
267
268 header('Content-type: text/x-csv; encoding=iso-8859-1');
269 header('Pragma: ');
270 header('Cache-Control: ');
271
272 $page->changeTpl('xnetevents/csv.tpl', NO_SKIN);
273
274 $admin = may_update();
275
276 $tri = (Env::v('order') == 'alpha' ? 'promo, nom, prenom' : 'nom, prenom, promo');
277
278 $page->assign('participants',
279 get_event_participants($evt, $item_id, $tri));
280
281 $page->assign('admin', $admin);
282 $page->assign('moments', $evt['moments']);
283 $page->assign('money', $evt['money']);
284 $page->assign('tout', !Env::v('item_id', false));
285 }
286
287 function handler_ical(&$page, $eid = null)
288 {
289 global $globals;
290
291 require_once dirname(__FILE__).'/xnetevents/xnetevents.inc.php';
292 $evt = get_event_detail($eid);
293 if (!$evt) {
294 return PL_FORBIDDEN;
295 }
296 $evt['debut'] = preg_replace('/(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/', "\\1\\2\\3T\\4\\5\\6", $evt['debut']);
297 $evt['fin'] = preg_replace('/(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)/', "\\1\\2\\3T\\4\\5\\6", $evt['fin']);
298
299 foreach ($evt['moments'] as $m) {
300 $evt['descriptif'] .= "\n\n** " . $m['titre'] . " **\n" . $m['details'];
301 }
302
303 $page->changeTpl('xnetevents/calendar.tpl', NO_SKIN);
304
305 require_once('ical.inc.php');
306 $page->assign('asso', $globals->asso());
307 $page->assign('timestamp', time());
308 $page->assign('admin', may_update());
309
310 if (may_update()) {
311 $page->assign('participants', get_event_participants($evt, null, 'promo, nom, prenom'));
312 }
313 $page->register_function('display_ical', 'display_ical');
314 $page->assign_by_ref('e', $evt);
315
316 header('Content-Type: text/calendar; charset=utf-8');
317 }
318
319 function handler_edit(&$page, $eid = null)
320 {
321 global $globals;
322
323 // get eid if the the given one is a short name
324 if (!is_null($eid) && !is_numeric($eid)) {
325 $res = XDB::query("SELECT eid
326 FROM groupex.evenements
327 WHERE asso_id = {?} AND short_name = {?}",
328 $globals->asso('id'), $eid);
329 if ($res->numRows()) {
330 $eid = (int)$res->fetchOneCell();
331 }
332 }
333
334 // check the event is in our group
335 if (!is_null($eid)) {
336 $res = XDB::query("SELECT short_name
337 FROM groupex.evenements
338 WHERE eid = {?} AND asso_id = {?}",
339 $eid, $globals->asso('id'));
340 if ($res->numRows()) {
341 $infos = $res->fetchOneAssoc();
342 } else {
343 return PL_FORBIDDEN;
344 }
345 }
346
347 new_groupadmin_page('xnetevents/edit.tpl');
348
349 $moments = range(1, 4);
350 $error = false;
351 $page->assign('moments', $moments);
352
353 if (Post::v('intitule')) {
354 require_once dirname(__FILE__).'/xnetevents/xnetevents.inc.php';
355 $short_name = event_change_shortname($page, $infos['short_name'],
356 Env::v('short_name', ''));
357 if ($short_name != Env::v('short_name')) {
358 $error = true;
359 }
360 $evt = array(
361 'eid' => $eid,
362 'asso_id' => $globals->asso('id'),
363 'paiement_id' => Post::v('paiement_id') > 0 ? Post::v('paiement_id') : null,
364 'debut' => Post::v('deb_Year').'-'.Post::v('deb_Month')
365 .'-'.Post::v('deb_Day').' '.Post::v('deb_Hour')
366 .':'.Post::v('deb_Minute').':00',
367 'fin' => Post::v('fin_Year').'-'.Post::v('fin_Month')
368 .'-'.Post::v('fin_Day').' '.Post::v('fin_Hour')
369 .':'.Post::v('fin_Minute').':00',
370 'short_name' => $short_name,
371 );
372
373 $trivial = array('intitule', 'descriptif', 'noinvite',
374 'show_participants', 'accept_nonmembre', 'organisateur_uid');
375 foreach ($trivial as $k) {
376 $evt[$k] = Post::v($k);
377 }
378 if (!$eid) {
379 $evt['organisateur_uid'] = S::v('uid');
380 }
381
382 if (Post::v('deadline')) {
383 $evt['deadline_inscription'] = Post::v('inscr_Year').'-'
384 . Post::v('inscr_Month').'-'
385 . Post::v('inscr_Day');
386 } else {
387 $evt['deadline_inscription'] = null;
388 }
389
390 // Store the modifications in the database
391 XDB::execute('REPLACE INTO groupex.evenements
392 SET eid={?}, asso_id={?}, organisateur_uid={?}, intitule={?},
393 paiement_id = {?}, descriptif = {?}, debut = {?},
394 fin = {?}, show_participants = {?}, short_name = {?},
395 deadline_inscription = {?}, noinvite = {?},
396 accept_nonmembre = {?}',
397 $evt['eid'], $evt['asso_id'], $evt['organisateur_uid'],
398 $evt['intitule'], $evt['paiement_id'], $evt['descriptif'],
399 $evt['debut'], $evt['fin'], $evt['show_participants'],
400 $evt['short_name'], $evt['deadline_inscription'],
401 $evt['noinvite'], $evt['accept_nonmembre']);
402
403 // if new event, get its id
404 if (!$eid) {
405 $eid = XDB::insertId();
406 }
407
408 $nb_moments = 0;
409 $money_defaut = 0;
410
411 foreach ($moments as $i) {
412 if (Post::v('titre'.$i)) {
413 $nb_moments++;
414
415 $montant = strtr(Post::v('montant'.$i), ',', '.');
416 $money_defaut += (float)$montant;
417 XDB::execute("
418 REPLACE INTO groupex.evenements_items
419 VALUES ({?}, {?}, {?}, {?}, {?})",
420 $eid, $i, Post::v('titre'.$i),
421 Post::v('details'.$i), $montant);
422 } else {
423 XDB::execute("DELETE FROM groupex.evenements_items
424 WHERE eid = {?} AND item_id = {?}", $eid, $i);
425 }
426 }
427 // request for a new payment
428 if (Post::v('paiement_id') == -1 && $money_defaut >= 0) {
429 require_once 'validations.inc.php';
430 $p = new PayReq(S::v('uid'),
431 Post::v('intitule')." - ".$globals->asso('nom'),
432 Post::v('site'), $money_defaut,
433 Post::v('confirmation'), 0, 999,
434 $globals->asso('id'), $eid);
435 $p->submit();
436 }
437
438 // events with no sub-event: add a sub-event with no name
439 if ($nb_moments == 0) {
440 XDB::execute("INSERT INTO groupex.evenements_items
441 VALUES ({?}, {?}, '', '', 0)", $eid, 1);
442 }
443
444 if (!$error) {
445 pl_redirect('events');
446 }
447 }
448
449 // get a list of all the payment for this asso
450 $res = XDB::iterator("SELECT id, text
451 FROM {$globals->money->mpay_tprefix}paiements
452 WHERE asso_id = {?}", $globals->asso('id'));
453 $paiements = array();
454 while ($a = $res->next()) $paiements[$a['id']] = $a['text']; {
455 $page->assign('paiements', $paiements);
456 }
457
458 // when modifying an old event retreive the old datas
459 if ($eid) {
460 $res = XDB::query(
461 "SELECT eid, intitule, descriptif, debut, fin, organisateur_uid,
462 show_participants, paiement_id, short_name,
463 deadline_inscription, noinvite, accept_nonmembre
464 FROM groupex.evenements
465 WHERE eid = {?}", $eid);
466 $evt = $res->fetchOneAssoc();
467 // find out if there is already a request for a payment for this event
468 require_once 'validations.inc.php';
469 $res = XDB::query("SELECT stamp FROM requests
470 WHERE type = 'paiements' AND data LIKE {?}",
471 PayReq::same_event($eid, $globals->asso('id')));
472 $stamp = $res->fetchOneCell();
473 if ($stamp) {
474 $evt['paiement_id'] = -2;
475 $evt['paiement_req'] = $stamp;
476 }
477 $page->assign('evt', $evt);
478 // get all the different moments infos
479 $res = XDB::iterator(
480 "SELECT item_id, titre, details, montant
481 FROM groupex.evenements_items AS ei
482 INNER JOIN groupex.evenements AS e ON(e.eid = ei.eid)
483 WHERE e.eid = {?}
484 ORDER BY item_id", $eid);
485 $items = array();
486 while ($item = $res->next()) {
487 $items[$item['item_id']] = $item;
488 }
489 $page->assign('items', $items);
490 }
491 $page->assign('url_ref', $eid);
492 }
493
494 function handler_admin(&$page, $eid = null, $item_id = null)
495 {
496 global $globals;
497
498 require_once dirname(__FILE__).'/xnetevents/xnetevents.inc.php';
499
500 $evt = get_event_detail($eid, $item_id);
501 if (!$evt) {
502 return PL_NOT_FOUND;
503 }
504
505 if ($evt['show_participants']) {
506 new_group_page('xnetevents/admin.tpl');
507 } else {
508 new_groupadmin_page('xnetevents/admin.tpl');
509 }
510
511 if (may_update() && Post::v('adm')) {
512 $member = get_infos(Post::v('mail'));
513 if (!$member) {
514 $page->trig("Membre introuvable");
515 }
516
517 // change the price paid by a participant
518 if (Env::v('adm') == 'prix' && $member) {
519 XDB::execute("UPDATE groupex.evenements_participants
520 SET paid = IF(paid + {?} > 0, paid + {?}, 0)
521 WHERE uid = {?} AND eid = {?}",
522 strtr(Env::v('montant'), ',', '.'),
523 strtr(Env::v('montant'), ',', '.'),
524 $member['uid'], $evt['eid']);
525 }
526
527 // change the number of personns coming with a participant
528 if (Env::v('adm') == 'nbs' && $member) {
529 $res = XDB::query("SELECT paid
530 FROM groupex.evenements_participants
531 WHERE uid = {?} AND eid = {?}",
532 $member['uid'], $evt['eid']);
533
534 $paid = intval($res->fetchOneCell());
535 $nbs = Post::v('nb', array());
536
537 foreach ($nbs as $id => $nb) {
538 $nb = max(intval($nb), 0);
539 XDB::execute("REPLACE INTO groupex.evenements_participants
540 VALUES ({?}, {?}, {?}, {?}, {?})",
541 $evt['eid'], $member['uid'], $id, $nb, $paid);
542 }
543
544 $res = XDB::query("SELECT COUNT(uid) AS cnt, SUM(nb) AS nb
545 FROM groupex.evenements_participants
546 WHERE uid = {?} AND eid = {?}
547 GROUP BY uid",
548 $member['uid'], $evt['eid']);
549 $u = $res->fetchOneAssoc();
550 $u = $u['cnt'] ? null : $u['nb'];
551 subscribe_lists_event($u, $member['uid'], $evt);
552 }
553
554 $evt = get_event_detail($eid, $item_id);
555 }
556
557 $page->assign('evt', $evt);
558 $page->assign('tout', is_null($item_id));
559
560 if (count($evt['moments'])) {
561 $page->assign('moments', $evt['moments']);
562 }
563
564 $tri = (Env::v('order') == 'alpha' ? 'promo, nom, prenom' : 'nom, prenom, promo');
565 $whereitemid = is_null($item_id) ? '' : "AND ep.item_id = $item_id";
566 $res = XDB::iterRow(
567 'SELECT UPPER(SUBSTRING(IF(u.nom IS NULL, m.nom,
568 IF(u.nom_usage<>"", u.nom_usage, u.nom)), 1, 1)),
569 COUNT(DISTINCT ep.uid)
570 FROM groupex.evenements_participants AS ep
571 INNER JOIN groupex.evenements AS e ON (ep.eid = e.eid)
572 LEFT JOIN groupex.membres AS m ON ( ep.uid = m.uid AND e.asso_id = m.asso_id)
573 LEFT JOIN auth_user_md5 AS u ON ( u.user_id = ep.uid )
574 WHERE ep.eid = {?} '.$whereitemid.'
575 GROUP BY UPPER(SUBSTRING(IF(u.nom IS NULL,m.nom,u.nom), 1, 1))', $evt['eid']);
576
577 $alphabet = array();
578 $nb_tot = 0;
579 while (list($char, $nb) = $res->next()) {
580 $alphabet[ord($char)] = $char;
581 $nb_tot += $nb;
582 if (Env::has('initiale') && $char == strtoupper(Env::v('initiale'))) {
583 $tot = $nb;
584 }
585 }
586 ksort($alphabet);
587 $page->assign('alphabet', $alphabet);
588
589 $ofs = Env::i('offset');
590 $tot = Env::v('initiale') ? $tot : $nb_tot;
591 $nbp = intval(($tot-1)/NB_PER_PAGE);
592 $links = array();
593 if ($ofs) {
594 $links['précédent'] = $ofs-1;
595 }
596 for ($i = 0; $i <= $nbp; $i++) {
597 $links[(string)($i+1)] = $i;
598 }
599 if ($ofs < $nbp) {
600 $links['suivant'] = $ofs+1;
601 }
602 if (count($links)>1) {
603 $page->assign('links', $links);
604 }
605
606 if ($evt['paiement_id']) {
607 $res = XDB::iterator(
608 "SELECT IF(u.nom_usage<>'', u.nom_usage, u.nom) AS nom, u.prenom,
609 u.promo, a.alias AS email, t.montant
610 FROM {$globals->money->mpay_tprefix}transactions AS t
611 INNER JOIN auth_user_md5 AS u ON(t.uid = u.user_id)
612 INNER JOIN aliases AS a ON (a.id = t.uid AND a.type='a_vie' )
613 LEFT JOIN groupex.evenements_participants AS ep ON(ep.uid = t.uid AND ep.eid = {?})
614 WHERE t.ref = {?} AND ep.uid IS NULL",
615 $evt['eid'], $evt['paiement_id']);
616 $page->assign('oublis', $res->total());
617 $page->assign('oubliinscription', $res);
618 }
619
620 $page->assign('participants',
621 get_event_participants($evt, $item_id, $tri,
622 "LIMIT ".($ofs*NB_PER_PAGE).", ".NB_PER_PAGE));
623 }
624 }
625
626 ?>