schedule/schedules.class.php
2023-10-13 06:43:02 +02:00

1664 lines
80 KiB
PHP

<?php
/**
* @license http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html
* @author Francois Merciol <dokuplugin@merciol.fr>
*
* Plugin Schedule: manage events per wiki @groups
// TODO :
// passer des actions suivant langue en actions neutres
// selection automatique de cantons suivant lieu si existe le canton existe
// radius dans conf puis select
*/
if (!defined ('DOKU_INC'))
define ('DOKU_INC', realpath (dirname (__FILE__).'/../../../').'/');
if (!defined ('DOKU_PLUGIN'))
define ('DOKU_PLUGIN', DOKU_INC.'lib/plugins/');
require_once (realpath (dirname (__FILE__)).'/scheduleInseeCities.php');
// ============================================================
// management event class
class schedules {
// ============================================================
// Config attributs
// ============================================================
var $scheduleRoot; // commun data for all schedules
var $nameSpace; // namespace where definition could be found
var $lastNotification; // time of last proposal notification
var $lastNotificationReset; // time of last administrators acknowledgement
var $md5ns; // the ns directory
var $cacheDir; // cache directory
var $dataDir; // schedule database
var $migrate; // performe data migration
var $showOldValues; // highlight non migrate data
// ============================================================
// Transcient attributs
// ============================================================
var $allGroups = array (); // dynamique set of groups name
var $allSchedules = array (); // set of all events
var $memberSchedules = array (); // set of events indexed by member
var $repeatedSchedules = array (); // set of repeated events indexed by date
var $fixedSchedules = array (); // set of non repeated events indexed by date
var $datedSchedules = array (); // set of repeated or not events indexed by date
var $membersToSave = array (); // set of modified members
var $allProposals = array (); // set of all proposals
var $proposalsToSave = false; // modified proposals
var $printProp = false; // display proposal event form
var $printForm = false; // display add event form
var $printCtrl = false; // display action event form
var $isShow = false; // date focus flag mode
var $userGroups = array (); // set of user group wich are schedule groupe
var $defaultSchedule; // empty schedule model
var $before; // before filter date
var $date; // exact filter date
var $after; // after filter date
var $max; // max events lines
var $filters;
// ============================================================
// Util
// ============================================================
function getConf ($name) {
return $this->scheduleRoot->plugin->getConf ($name);
}
function getLang ($name) {
return $this->scheduleRoot->plugin->getLang ($name);
}
function isAdmin () {
return $this->scheduleRoot->isAdmin;
}
function message ($type, $text) {
return $this->scheduleRoot->message ($type, $text);
}
function startMessage ($type, $text) {
return $this->scheduleRoot->startMessage ($type, $text);
}
function debug ($text) {
return $this->scheduleRoot->debug ($text);
}
function isMessage ($type) {
return isset ($this->scheduleRoot->message[$type]);
}
// ============================================================
function __construct ($scheduleRoot, $ns) {
$this->scheduleRoot = $scheduleRoot;
$this->defaultSchedule = new schedule ();
$this->nameSpace = cleanId (trim ($ns));
$this->md5ns = md5 ($this->nameSpace);
$this->cacheDir = $this->scheduleRoot->cacheRootDir.$this->md5ns.'/';
$this->dataDir = $this->scheduleRoot->dataRootDir.$this->md5ns.'/';
$this->migrate = $this->getConf ('migrate');
$this->showOldValues = $this->getConf ('showOldValues');
if ($this->migrate) {
global $scheduleInseeCities, $scheduleCitiesInsee;
$scheduleCitiesInsee = array ();
foreach ($scheduleInseeCities as $insee => $cityDef)
$scheduleCitiesInsee [strtolower ($cityDef[0])] = $insee;
}
$config = $this->scheduleRoot->readConfig ($this->dataDir);
if (!$config)
$this->scheduleRoot->writeConfig ($this);
else
foreach ($this->scheduleRoot->configAttributsName as $field)
if (isset ($config [$field]))
$this->$field = $config [$field];
}
/** XXX utilisé par scheduleRoot ?! */
function load () {
$exclude_array = explode ('|', '.|..');
global $conf;
$pathDir = $conf['savedir'].'/pages/'.trim ($this->scheduleRoot->groupsDir, '/') . '/';
if (is_dir($pathDir)) {
$pathDirObj = opendir ($pathDir);
while (false !== ($file = readdir ($pathDirObj))) {
if (in_array (strtolower ($file), $exclude_array))
continue;
$pathFile = $pathDir . $file;
// XXX precedent se trouve dans les membres ???
if (is_dir ($pathFile) && !in_array ($file, explode (',', trim ($this->getConf ('noSchedule')))))
$this->allGroups [] = $file;
}
}
sort ($this->allGroups);
global $INFO;
if (isset ($INFO ['userinfo']) && isset ($INFO ['userinfo']['grps'])) {
$userGroups = array ();
$scheduleGroup = false;
foreach ($INFO['userinfo']['grps'] as $tmpMember) {
$tmpMember = trim ($tmpMember);
if ($this->scheduleRoot->scheduleGroup == $tmpMember)
$scheduleGroup = true;
if (in_array ($tmpMember, $this->allGroups))
$userGroups [] = $tmpMember;
}
if ($scheduleGroup)
$this->userGroups = $userGroups;
}
$this->readSchedules ($this->dataDir);
$this->readProp ();
}
function isMember ($member) {
return $this->isAdmin () || in_array ($member, $this->userGroups);
}
function isAMemberOf ($members) {
if ($this->isAdmin ())
return true;
foreach ($members as $member)
if (in_array ($member, $this->userGroups))
return true;
return false;
}
function isMemberOfAll ($members) {
if ($this->isAdmin ())
return true;
foreach ($members as $member)
if (!in_array ($member, $this->userGroups))
return false;
return true;
}
// ============================================================
function readCache ($key) {
if (!is_dir ($this->cacheDir))
return false;
$filename = $this->cacheDir.md5 ($key).'.cache';
if (!file_exists ($filename))
return false;
// YYY date du fichier (le calendrier change tous les jours)
if (filemtime ($filename) < strtotime ('today'))
return false;
// XXX ??? Warning: file_get_contents() [function.file-get-contents]: failed to open stream: No such file or directory in on line 153
return file_get_contents ($filename);
}
function writeCache ($key, $text) {
scheduleRoot::createDirIsNeeded ($this->cacheDir);
$filename = $this->cacheDir.md5 ($key).'.cache';
file_put_contents ($filename, $text);
}
function clearCache () {
if (!$this->isAdmin ())
return;
$exclude = '.|..|'.$this->scheduleRoot->configFile;
$exclude_array = explode('|', $exclude);
$pathDir = $this->cacheDir;
if (!is_dir($pathDir))
return;
$pathDirObj = opendir ($pathDir);
while (false !== ($file = readdir ($pathDirObj))) {
if (in_array (strtolower ($file), $exclude_array))
continue;
$pathFile = $pathDir . $file;
if (is_file ($pathFile) && preg_match ('#.*\.cache#i', $file, $b))
unlink ($pathFile);
}
@rmdir ($pathDir);
}
// ============================================================
function setDateFilters ($before, $date, $after) {
$this->before = $this->scheduleRoot->df2ds ($before);
$this->after = $this->scheduleRoot->df2ds ($after);
$this->date = $this->scheduleRoot->df2ds ($date);
if ($this->date)
$this->before = $this->after = $this->date;
}
// ============================================================
function setFormLevel ($formLevel) {
global $INFO;
if ($formLevel > 2)
$this->printProp = true;
if (($formLevel > 0) &&
isset ($INFO ['userinfo']) &&
isset ($INFO ['userinfo']['grps']))
foreach ($INFO['userinfo']['grps'] as $tmpMember) {
$tmpMember = trim ($tmpMember);
if ($this->scheduleRoot->scheduleGroup == $tmpMember) {
if ($formLevel > 1)
$this->printForm = true;
$this->printCtrl = true;
$this->printProp = false;
break;
}
}
}
// ============================================================
function setOtherFilters ($max, $filters, $grouped) {
$this->max = $max;
foreach ($filters as $name => $values) {
$newValues = array ();
foreach (explode (',', $values) as $value) {
$value = trim ($value);
if (! empty ($value))
$newValues [] = $value;
}
if (!empty ($newValues))
$this->filters[$name] = $newValues;
}
$this->repeatGrouped = trim ($this->getConf ('repeatPosition')) == 'grouped';
$grouped = trim ($grouped);
if (in_array ($grouped, array ('grouped', 'isolated')))
$this->repeatGrouped = $grouped == 'grouped';
}
// ============================================================
// Manage XML file
// ============================================================
/* Save a member data base */
function writeSchedule ($member) {
$xml = new DOMDocument ('1.0', 'utf8');
$root = $xml->createElement ('schedule');
$root->setAttribute ('member', $member);
$xml->appendChild ($root);
foreach ($this->memberSchedules [$member] as $id => $schedule) {
$event = $xml->createElement ('event');
foreach ($this->scheduleRoot->scheduleSaveAttributsName as $field)
$event->appendChild ($xml->createElement ($field, htmlspecialchars ($schedule->$field)));
$root->appendChild ($event);
}
$xml->formatOutput = true;
$fileName = $this->dataDir.$this->scheduleRoot->mbrPrefix.$member.'.xml';
$xml->save ($fileName);
chmod ($fileName, 0664);
}
function readProp () {
$this->readSchedule ($this->dataDir.$this->scheduleRoot->propFile, true);
}
function writeProp () {
// if (! class_exists ('DOMDocument'))
// return;
$xml = new DOMDocument ('1.0', 'utf8');
$root = $xml->createElement ('schedule');
$root->setAttribute ('member', 'proposal');
$xml->appendChild ($root);
foreach ($this->allProposals as $id => $schedule) {
$event = $xml->createElement ('event');
foreach ($this->scheduleRoot->scheduleSaveAttributsName as $field)
$event->appendChild ($xml->createElement ($field, htmlspecialchars ($schedule->$field)));
$event->appendChild ($xml->createElement ('member', htmlspecialchars ($schedule->member)));
$root->appendChild ($event);
}
$xml->formatOutput = true;
$fileName = $this->dataDir.$this->scheduleRoot->propFile;
$xml->save ($fileName);
chmod ($fileName, 0664);
}
/* Migrate where format */
function whereMigrate ($schedule, $sep) {
global $scheduleCitiesInsee;
if (!$schedule)
return false;
if (preg_match ('/[0-9]/', $schedule->where)) {
return false;
}
$newFields = array ();
$updated = false;
foreach (explode ($sep, $schedule->where) as $city) {
$city = trim ($city);
if (!$city)
continue;
$insee = $scheduleCitiesInsee [strtolower ($city)];
$newFields [] = $insee ? $insee : $city;
if ($insee)
$updated = true;
}
$newWhere = implode (',', $newFields);
if (!$newWhere || !$updated)
return false;
$schedule->where = $newWhere;
return true;
}
/* Read a member data base */
function readSchedule ($file, $prop = false) {
if (!file_exists ($file))
return;
// if (! class_exists ('DOMDocument'))
// return;
$xml = new DOMDocument ('1.0', 'utf8');
$xml->load ($file);
$root = $xml->documentElement;
$member = $root->getAttribute ('member');
$events = $root->getElementsByTagName ('event');
for ($i = $events->length; --$i >= 0; ) {
$event = $events->item ($i);
$schedule = new schedule ();
foreach ($this->scheduleRoot->scheduleSaveAttributsName as $field) {
$element = $event->getElementsByTagName ($field);
if ($element)
$schedule->$field = $element->item (0)->nodeValue;
}
if ($prop) {
$element = $event->getElementsByTagName ('member');
if ($element)
$schedule->member = $element->item (0)->nodeValue;
} else
$schedule->member = $member;
if ($this->migrate && !$prop &&
($this->whereMigrate ($schedule, ',') ||
$this->whereMigrate ($schedule, '/') ||
$this->whereMigrate ($schedule, ' - ') ||
$this->whereMigrate ($schedule, ' ')))
$this->membersToSave [$member] = true;
// XXX compatibilité
$schedule->shared = ($schedule->shared == true);
$schedule->repeatFlag = $schedule->to != '' && $schedule->from != $schedule->to;
if ($prop)
$this->allProposals [$schedule->id] = $schedule;
else
$this->allSchedules [$schedule->id] = $schedule;
}
}
// ============================================================
// IO functions
// ============================================================
/* Read all member data base */
function readSchedules ($pathDir) {
$exclude = '.|..|'.$this->scheduleRoot->configFile;
$exclude_array = explode('|', $exclude);
$pathDir = rtrim ($pathDir, '/') . '/';
if (!is_dir($pathDir))
return;
$pathDirObj = opendir ($pathDir);
while (false !== ($file = readdir ($pathDirObj))) {
if (in_array (strtolower ($file), $exclude_array))
continue;
$pathFile = $pathDir . $file;
if (is_file ($pathFile) &&
preg_match ('#'.$this->scheduleRoot->mbrPrefix.'.*\.xml$#i', $file, $b))
$this->readSchedule ($pathFile);
}
$this->updateSchedulesLists ();
}
// ============================================================
/* Save all member data base marked as modified */
function writeSchedules () {
if (!count ($this->membersToSave))
return;
foreach (array_keys ($this->membersToSave) as $member)
if (count ($this->memberSchedules [$member]) <= 0)
@unlink ($this->dataDir.$this->scheduleRoot->mbrPrefix.$member.'.xml');
else
$this->writeSchedule ($member);
$this->clearCache ();
}
// ============================================================
// YYY
// ============================================================
/* get all siblings shared events but the pattern */
function getOtherSharedEvents ($event) {
$result = array ();
if (!$event->from)
return $result;
foreach ($this->datedSchedules [$event->from] as $other)
if ($event->shared == $other->shared &&
$event->to == $other->to &&
$event->at == $other->at &&
$event->title == $other->title &&
$event->id != $other->id)
$result [] = $other;
return $result;
}
// ============================================================
/* XXX */
function getMembersSharedEvents ($event) {
if (!$event->shared || !$event->from || !$event->title)
return $event->requestMembers ? $event->requestMembers : array ($event->member);
$result = array ();
foreach ($this->datedSchedules [$event->from] as $other)
if ($event->shared == $other->shared &&
$event->to == $other->to &&
$event->at == $other->at &&
$event->title == $other->title)
$result [] = $other->member;
return $result;
}
// ============================================================
/* Performe action */
function manageAction ($request) {
if ($request['action'] == $this->getLang ('show')) {
$this->isShow = true;
if (isset ($request['date'])) {
$this->before = $this->after = $this->date = $this->scheduleRoot->df2ds ($request['date']);
}
} elseif ($request['action'] == $this->getLang ('selected')) {
if (isset ($request['id'])) {
$id = $request['id'];
if (isset ($this->allProposals [$id])) {
$this->defaultSchedule = $this->allProposals [$id];
$this->defaultSchedule->prop = true;
} else if (isset ($this->allSchedules [$id])) {
$this->defaultSchedule = $this->allSchedules [$id];
}
}
} elseif (in_array ($request['action'],
array ($this->getLang ('modifyAll'),
$this->getLang ('modify'),
$this->getLang ('add'),
$this->getLang ('valid'),
$this->getLang ('prop')))) {
if (isset ($request['id']))
$id = $request['id'];
$this->manageAddAction ($request);
if ($request['action'] == $this->getLang ('valid'))
$this->removeSchedule ($id);
} elseif ($request['action'] == $this->getLang ('remove')) {
if (isset ($request['idl']))
foreach ($request['idl'] as $id)
$this->removeSchedule ($id);
unset ($_REQUEST['schd']);
} elseif ($request['action'] == $this->getLang ('created'))
$this->manageCreateAction ($request);
}
// ============================================================
function manageAddAction ($request) {
if (isset ($request['id']))
$id = $request['id'];
$schedule = new schedule ();
$others = array ();
$oldMember = '';
if (isset ($this->allSchedules [$id]) &&
($request['action'] == $this->getLang ('modifyAll') ||
$request['action'] == $this->getLang ('modify'))) {
$schedule = &$this->allSchedules [$id];
$oldMember = $schedule->member;
if ($request['action'] == $this->getLang ('modifyAll'))
$others = $this->getOtherSharedEvents ($schedule);
}
foreach ($this->scheduleRoot->scheduleRequestAttributsName as $field)
$schedule->$field = trim (str_replace (array ('"'), '', $request [$field]));
if ($request ['member']) {
$schedule->requestMembers = explode (',', trim (str_replace (',,', ',', $request ['member']), ','));
$schedule->member = trim ($schedule->requestMembers [0]);
}
$schedule->title = strtr ($schedule->title, '"', "''");
$schedule->lead = strtr ($schedule->lead, '"', "''");
$schedule->remark = strtr ($schedule->remark, '"', "''");
$schedule->weekDays = scheduleRoot::array2string ($request ['weekDays']);
$schedule->from = $this->scheduleRoot->df2ds ($request ['from']);
$schedule->to = $this->scheduleRoot->df2ds ($request ['to']);
if ('' == $schedule->from) {
$schedule->from = $schedule->to;
$schedule->to = '';
}
if ($schedule->from == $schedule->to)
$schedule->to = '';
if ('' == $schedule->from && '' == $schedule->where && '' == $schedule->title) {
$this->defaultSchedule = $schedule;
unset ($_REQUEST['schd']);
return;
}
if (!$this->printProp && $schedule->member && !$this->isMemberOfAll ($schedule->requestMembers)) {
$this->message ('info', $this->getLang ('notMemberError'));
$this->defaultSchedule = $schedule;
unset ($_REQUEST['schd']);
return;
}
if (!$request ['audience'])
$this->message ('error', $this->getLang ('noAudienceError'));
if (!$schedule->member)
$this->message ('error', $this->getLang ('noMemberError'));
if ('' == $schedule->what)
$this->message ('error', $this->getLang ('noTypeError'));
if ('' == $schedule->title)
$this->message ('error', $this->getLang ('noTitleError'));
if ('' == $schedule->where)
$this->message ('error', $this->getLang ('noWhereError'));
if (!$this->scheduleRoot->checkDS ($schedule->from))
$this->message ('error', $request ['from'].' : '.$this->getLang ('badDateError'));
if ($schedule->to && !$this->scheduleRoot->checkDS ($schedule->to))
$this->message ('error', $request ['to'].' : '.$this->getLang ('badDateError'));
else if ($this->after && ($schedule->to ? $schedule->to : $schedule->from) < $this->after)
$this->message ('error', $request ['from'].' : '.$this->getLang ('pastError'));
else if ($schedule->to != '' && $schedule->from > $schedule->to)
$this->message ('error', $request ['to'].' : '.$this->getLang ('pastToError'));
if ($this->isMessage ('error')) {
$this->startMessage ('error', $this->getLang ('startError'));
$this->defaultSchedule = $schedule;
unset ($_REQUEST['schd']);
return;
}
$schedule->repeatFlag = $schedule->to != '' && $schedule->from != $schedule->to;
// force un nouvel id, member et file
if (!$schedule->id || in_array ($request['action'],
array ($this->getLang ('add'),
$this->getLang ('valid'),
$this->getLang ('prop'))))
$schedule->id = date ('Ymdhis.0');
if ($this->printProp) {
unset ($_REQUEST['schd']);
if (!$captcha =& plugin_load ('helper', 'captcha') ||
!$captcha->check ()) {
$this->defaultSchedule = $schedule;
return;
}
$schedule->member = implode (',', $schedule->requestMembers);
$this->allProposals [] = $schedule;
$this->proposalsToSave = true;
$this->adminNotification ();
$this->message ('success', $this->getLang ('propSuccess'));
return;
}
if ($oldMember)
$this->membersToSave [$oldMember] = true;
global $INFO;
$schedule->user = $_SERVER['REMOTE_USER'];
$this->addSchedule ($schedule);
unset ($_REQUEST['schd']);
foreach ($others as $other) {
if (!$this->isMember ($others->member))
continue;
foreach ($this->scheduleRoot->scheduleSaveAttributsName as $field)
if ($field != 'id')
$other->$field = $schedule->$field;
$this->membersToSave [$other->member] = true;
}
$sharedMembers = $this->getMembersSharedEvents ($schedule);
$i = 1;
foreach ($schedule->requestMembers as $newMember) {
$newMember = trim ($newMember);
if (!$newMember || in_array ($newMember, $sharedMembers))
continue;
if (!$this->isMember ($newMember))
continue;
$newSchedule = new schedule ();
foreach ($this->scheduleRoot->scheduleSaveAttributsName as $field)
$newSchedule->$field = $schedule->$field;
$newSchedule->id = date ('Ymdhis').$i;
$i++;
$newSchedule->member = $newMember;
$this->addSchedule ($newSchedule);
}
$pageId = $this->scheduleRoot->getPageId ($schedule);
resolve_pageid ($this->nameSpace, $pageId, $exists);
if (!$exists)
return;
$content = io_readFile (wikiFN ($pageId));
$start = "";
$option = "";
$end = $content;
$place = trim ($this->makeListPlaceForMap ($schedule));
if (preg_match ("#(?<start>(.|\n)*)<schedule(?<option>[^>]*)>(?<place>([^<]|\n)*)</schedule>(?<end>(.|\n)*)#", $content, $dumy)) {
$start = $dumy ['start'];
$option = $dumy ['option'];
$place2 = trim ($dumy ['place']);
$end = $dumy ['end'];
if ($place == $place2)
return;
} else if (preg_match ("#(?<start>(.|\n)*=+ Lieu =+\n)(?<place>([^=]|=[^=]|\n)*)(?<end>\n=(.|\n)*)#", $content, $dumy)) {
$start = $dumy ['start'].NL;
$end = $dumy ['end'];
} else {
$start = '===== Lieu ====='.NL.NL;
$end = $content;
}
$content = $start.'<schedule'.$option.'>'.NL.$place.NL.'</schedule>'.NL.$end;
saveWikiText ($pageId, $content, 'update place');
}
// ============================================================
function manageCreateAction ($request) {
$id = $request['id'];
$pageId = $request ['pageId'];
resolve_pageid ($this->nameSpace, $pageId, $exists);
if (!$exists && isset ($this->allSchedules [$id])) {
$schedule = $this->allSchedules [$id];
$sharedMembers = $this->getMembersSharedEvents ($schedule);
// XXX mettre date, lieu, sujet, tarif dans langue
$content = '';
foreach ($sharedMembers as $member)
$content .=
'[[:'.$this->scheduleRoot->groupsDir.':'.$member.':|'.
'{{ :'.$this->scheduleRoot->groupsDir.':'.$member.':'.$this->scheduleRoot->iconName.'?100}}]]'.NL;
$content .=
'~~NOTOC~~'.NL.
'====== '.$schedule->title.' ======'.NL.NL;
if ($schedule->lead)
$content .=
str_replace ("''", '"', $schedule->lead).NL.NL;
$content .=
'===== Date ====='.NL.NL.
($schedule->repeatFlag ?
$this->makeRepeatString ($schedule, true) :
('Le '. $this->scheduleRoot->ds2ln ($schedule->from, true))).
$this->makePrettyAt ($schedule->at).NL.NL.
'===== Lieu ====='.NL.NL.
'<schedule>'.NL.
$this->makeListPlaceForMap ($schedule).
'</schedule>'.NL.NL.
'===== Sujet ====='.NL.NL;
if (!$schedule->remark)
$content .=
'<wrap round todo>Sujet à préciser</wrap>'.NL.NL;
if ($schedule->posterURL)
$content .=
'{{ '.$schedule->posterURL.'?direct&200|}}'.NL;
if ($schedule->paperURL)
$content .=
'[['.$schedule->paperURL.' |]]'.NL;
if ($schedule->remark)
$content .=
str_replace ("''", '"', $schedule->remark).NL.NL;
if ($schedule->rate)
$content .=
'===== Tarif ====='.NL.NL.
$schedule->rate.NL;
saveWikiText ($pageId, $content, 'wizard creation');
$this->clearCache ();
}
unset ($_REQUEST['schd']);
}
// ============================================================
/* Add event */
function addSchedule (&$schedule) {
if (isset ($this->allSchedules [$schedule->id]))
unset ($this->allSchedules [$schedule->id]);
$this->membersToSave [$schedule->member] = true;
// élimine les doublons
if (isset ($this->memberSchedules [$schedule->member]))
foreach ($this->memberSchedules [$schedule->member] as $event)
if ($event->from == $schedule->from &&
$event->to == $schedule->to &&
$event->at == $schedule->at &&
$event->shared == $schedule->shared &&
$event->title == $schedule->title &&
$event->id != $schedule->id) {
unset ($this->allSchedules [$event->id]);
}
$this->allSchedules [$schedule->id] = $schedule;
$this->updateSchedulesLists ();
}
// ============================================================
/* Remove event */
function removeSchedule ($id) {
if (isset ($this->allProposals [$id])) {
$this->proposalsToSave = true;
unset ($this->allProposals [$id]);
$this->resetAdminNotification ();
} else if (isset ($this->allSchedules [$id])) {
$this->membersToSave [$this->allSchedules [$id]->member] = true;
unset ($this->allSchedules [$id]);
$this->updateSchedulesLists ();
}
}
// ============================================================
/* Update data base memory indexes after modification */
function updateSchedulesLists () {
$this->memberSchedules = array ();
$this->repeatedSchedules = array ();
$this->fixedSchedules = array ();
$this->datedSchedules = array ();
foreach ($this->allSchedules as $id => $schedule) {
$this->memberSchedules [$schedule->member][$id] = $schedule;
$this->datedSchedules [$schedule->from][] = $schedule;
if ($schedule->repeatFlag)
$this->repeatedSchedules [$schedule->from][] = $schedule;
else
$this->fixedSchedules [$schedule->from][] = $schedule;
}
foreach (array_keys ($this->memberSchedules) as $member)
uasort ($this->memberSchedules [$member], 'cmpSchedule');
uasort ($this->allSchedules, 'cmpSchedule');
}
// ============================================================
/* Print schedule as a matrix of days */
function printScheduleCalendar ($mapId, $dn_showDay) {
$nbDaysPerWeek = 7;
$nbWeeks = 5;
$nbDays = $nbDaysPerWeek * $nbWeeks;
$dn_today = mktime (0, 0, 0, date ('n'), date ('j'), date ('Y'));
$dn_start = mktime (0, 0, 0, date ('m', $dn_showDay), date ('d', $dn_showDay)-date ('w', $dn_showDay), date ('Y', $dn_showDay));
$dn_end = $dn_start + $nbDays * 86400;
$ds_start = date ('Ymd', $dn_start);
$ds_end = date ('Ymd', $dn_end);
$dn_prev = mktime (0, 0, 0, date ('m', $dn_showDay)-1, date ('d', $dn_showDay), date ('Y', $dn_showDay));
$dn_next = mktime (0, 0, 0, date ('m', $dn_showDay)+1, date ('d', $dn_showDay), date ('Y', $dn_showDay));
$df_prev = date ($this->scheduleRoot->currentDateFormat['prettyPrint'], $dn_prev);
$df_next = date ($this->scheduleRoot->currentDateFormat['prettyPrint'], $dn_next);
$dayNames = $this->getLang ('days');
ptln ('<table class="short" summary="schedule">'.NL.
' <caption class="'.($dn_showDay == $dn_today ? 'scheduleToday' : 'scheduleShow').'">'.NL.
' <div class="showBubbleOnFocus" style="float:left;">'.NL.
' <a onClick="scheduleChangeDate(this,\''.$this->nameSpace.'\',\''.$mapId.'\',\''.$df_prev.'\');">&lt;</a>'.NL.
' <div class="bubble '.$this->getConf ('bubblePosition').'Bubble">'.$this->getLang ('tipPrevM').'</div>'.NL.
' </div>'.NL.
' '.date ($this->scheduleRoot->currentDateFormat['prettyPrint'], $dn_showDay).NL.
' <div class="showBubbleOnFocus" style="float:right;">'.NL.
' <a onClick="scheduleChangeDate(this,\''.$this->nameSpace.'\',\''.$mapId.'\',\''.$df_next.'\');">&gt;</a>'.
' <div class="bubble '.$this->getConf ('bubblePosition').'Bubble">'.$this->getLang ('tipNextM').'</div>'.NL.
' </div>'.
' </caption>'.NL.
' <thead><tr><th></th>');
if ($dayNames)
foreach ($dayNames as $dayName => $dayAbrv)
echo '<th scope="col"><abbr title="'.$dayName.'">'.$dayAbrv.'</abbr></th>';
ptln (' </tr></thead>'.NL.
' <tbody onMouseOut="javascript:scheduleHighlightPOI (null)">');
$focusSchedules = array ();
$dn_day = $dn_start;
// copie des évènements non répété (à part quotidient)
for ($i = 0; $i < $nbDays; $i++) {
$ds_index = date ('Ymd', $dn_day);
if (isset ($this->fixedSchedules [$ds_index]))
$focusSchedules [$ds_index] = array_values ($this->fixedSchedules [$ds_index]);
$dn_day = mktime(0, 0, 0, date ('m', $dn_day) , date ('d', $dn_day)+1, date ('Y', $dn_day));
}
// extends repeated events
foreach ($this->repeatedSchedules as $ds_index => $events) {
foreach ($events as $event) {
if ($event->from >= $ds_end)
continue;
if ($event->to < $ds_start)
continue;
preg_match ("#(?<Y>[0-9]{4})(?<m>[0-9]{2})(?<d>[0-9]{2})#", $event->from, $dt_from);
$dn_from = $this->scheduleRoot->dt2dn ($dt_from);
if ($event->to > $ds_end)
$dn_to = $dn_end;
else {
preg_match ("#(?<Y>[0-9]{4})(?<m>[0-9]{2})(?<d>[0-9]{2})#", $event->to, $dt_to);
$dn_to = $this->scheduleRoot->dt2dn ($dt_to);
}
switch ($event->repeatType) {
// chercher le premier dans la fenêtre
// tant que dans la fenêtre répété la répétition
// ajouter l'évènement dans les autres
case 'day' :
// répétition des évènements quotidients
$dn_day = $dn_from;
$step = 86400 * $event->repeat;
if ($dn_from < $dn_start)
$dn_day += ceil (($dn_start - $dn_from) / $step) * $step;
for ( ; $dn_day <= $dn_to; $dn_day += $step)
$focusSchedules [date ('Ymd', $dn_day)][] = $event;
break;
case 'week' :
$dn_startWeek = mktime (0, 0, 0, date ('m', $dn_from), date ('d', $dn_from) - date ('w', $dn_from), date ('Y', $dn_from));
$step = 86400 * 7 * $event->repeat;
if ($dn_startWeek < $dn_start)
$dn_startWeek += floor (($dn_start - $dn_startWeek) / $step) * $step;
for ( ; $dn_startWeek <= $dn_to; $dn_startWeek += $step)
foreach (explode ('|', $event->weekDays) as $idd) {
$dn_day = $dn_startWeek + $idd * 86400;
if ($dn_day >= $dn_start && $dn_day >= $dn_from &&
$dn_day <= $dn_to)
$focusSchedules [date ('Ymd', $dn_day)][] = $event;
}
break;
case 'dayMonth' :
case 'dateMonth' :
$dn_startMonth = mktime (0, 0, 0, date ('m', $dn_from), 1, date ('Y', $dn_from));
if ($dn_startMonth < $dn_start) {
$nbMonth = floor ((date ('m', $dn_start) + date ('Y', $dn_start)*12 - (date ('m', $dn_from) + date ('Y', $dn_from)*12))/$event->repeat)*$event->repeat;
$dn_startMonth = mktime (0, 0, 0, date ('m', $dn_startMonth) + $nbMonth, 1, date ('Y', $dn_startMonth));
}
for ( ;
$dn_startMonth <= $dn_to;
$dn_startMonth = mktime (0, 0, 0, date ('m', $dn_startMonth) + $event->repeat, 1, date ('Y', $dn_startMonth))) {
$dn_day = $dn_startMonth;
if ($event->repeatType == 'dateMonth')
// XXX pb si moins de jour dans le mois
$dn_day = mktime (0, 0, 0, date ('m', $dn_startMonth), $event->dayRank, date ('Y', $dn_startMonth));
else {
$delta = $event->dayInWeek - date ('w', $dn_startMonth);
if ($delta < 0)
$delta += 7;
$delta += 7 * $event->weekRank;
// XXX pb si moins de jour dans le mois
$dn_day = mktime (0, 0, 0, date ('m', $dn_startMonth), $delta+1, date ('Y', $dn_startMonth));
}
if ($dn_day >= $dn_start && $dn_day >= $dn_from &&
$dn_day <= $dn_to)
$focusSchedules [date ('Ymd', $dn_day)][] = $event;
}
break;
case 'year' :
$dayInmonth = date ('j', $dn_from);
$monthInYear = date ('n', $dn_from);
$startYear = date ('Y', $dn_start) - (date ('Y', $dn_start) - date ('Y', $dn_from)) % $event->repeat;
$endYear = date ('Y', $dn_end);
for ( ; $startYear <= $endYear; $startYear += $event->repeat) {
$dn_day = mktime (0, 0, 0, $monthInYear, $dayInmonth, $startYear);
if ($dn_day >= $dn_start && $dn_day >= $dn_from &&
$dn_day <= $dn_to)
$focusSchedules [date ('Ymd', $dn_day)][] = $event;
}
break;
}
}
}
global $conf;
$dn_day = $dn_start;
$allLocations = '';
$LocationsEvents = array ();
for ($s = 0; $s < 5; $s++) {
$line = '';
for ($d = 0; $d < 7; $d++) {
$locations = '';
$df_day = date ($this->scheduleRoot->currentDateFormat['prettyPrint'], $dn_day);
$url = "javascript:scheduleSelectDate('".$df_day."');";
$bubble = '';
if ($d == 1)
$w = date ('W', $dn_day);
$class = 'day showBubbleOnFocus';
$dayRank = date ('d', $dn_day);
$eventClass = '';
if (isset ($focusSchedules [date ('Ymd', $dn_day)])) {
$eventClass = array ();
$nbEvent = 0;
$dayEvents = array ();
foreach ($focusSchedules [date ('Ymd', $dn_day)] as $event) {
$eventClass [preg_replace ("/\s/", '', htmlspecialchars (strtolower ($this->scheduleRoot->scheduleWhat [$event->what])))] = true;
$nbEvent++;
list ($LocationsEvents, $dayEvents, $locations) = $this->addLocationsDayEvent ($LocationsEvents, $dayEvents, $locations, $dn_day, $event);
}
$bubble = $this->getDayBubble ($dn_day, $dayEvents);
ksort ($eventClass);
$eventClass = 'cat_'.implode ('', array_keys ($eventClass));
$url = '?id='.$this->nameSpace.':'.$conf['start'].'&schd[ns]='.$this->nameSpace.'&schd[action]='.$this->getLang ('show').'&schd[date]='.$df_day;
$class .= ' '.$eventClass;
$class .= ' op_'.($nbEvent < 2 ? $nbEvent : 3);
}
if (!$bubble && $dn_day != $dn_today && $dn_day != $dn_showDay)
$class .= ' empty';
$locations = trim (implode (',', array_unique (explode (',', $locations))), ',');
$allLocations = trim (implode (',', array_unique (explode (',', $locations.','.$allLocations))), ',');
$over = '<div class="over mapSelect" style="display:none" day="'.$df_day.'" localtions="'.$locations.'" >'.$dayRank.'</div>';
if ($dn_day < $dn_today)
$over .= '<div class="over past">'.$dayRank.'</div>';
if ($d == 0 || $d == 6)
$class .= ' weekend';
if ($dn_day == $dn_today)
$over .= '<div class="over scheduleToday">'.$dayRank.'</div>';
elseif ($dn_day == $dn_showDay)
$over .= '<div class="over scheduleShow">'.$dayRank.'</div>';
$js = ' onMouseOver="javascript:scheduleHighlightPOI (\''.$locations.'\')"';
$line .= '<td class="'.$class.'"'.$js.'>'.$over.$bubble.'<a href="'.$url.'">'.$dayRank.'</a></td>';
$dn_day = mktime(0, 0, 0, date ('m', $dn_day), date ('d', $dn_day)+1, date ('Y', $dn_day));
}
echo '<tr><td class="week">'.$w.'</td>'.$line.'</tr>'.NL;
}
ptln (' </tbody>'.NL.
' <tfoot>'.NL.
' <tr><td colspan="8" class="map">'.NL.
$this->getCityBubble ($LocationsEvents).
' <div class="schedulePOI">'.NL.
' <div id="'.$mapId.'" class="scheduleMap scheduleMapCalendar"></div>'.NL.
' <span style="display:none;" class="poiLocations">'.$allLocations.'</span>'.NL.
' </div>'.NL.
' </td></tr>'.NL.
' </tfoot>'.NL.
'</table>');
}
// ============================================================
function getLocationsFromEvent ($event) {
$locations = '';
if ($event->lat && $event->lon) {
foreach (array_combine (explode (',', $event->lat), explode (',', $event->lon)) as $lat => $lon) {
$location = '('.$lat.'|'.$lon.')';
$locations .= ','.$location;
}
} elseif ($event->where) {
$location = $event->where;
$locations .= ','.$location;
}
return $locations;
}
function addLocationsDayEvent ($LocationsEvents, $dayEvents, $locations, $dn_day, $event) {
$pageId = $this->scheduleRoot->getPageId ($event);
resolve_pageid ($this->nameSpace, $pageId, $exists);
$logoId = $this->scheduleRoot->groupsDir.':'.$event->member.':'.$this->scheduleRoot->iconName;
$pageIdAt = $pageId.'-'.$event->at;
if ($dayEvents [$pageIdAt])
$dayEvents [$pageIdAt]['logo'][] = $logoId;
else
$dayEvents [$pageIdAt] =
array ('pageId'=> $pageId, 'logo' => array ($logoId),
'what'=> $event->what, 'where'=> $event->where, 'at' =>$event->at, 'title' => $event->title,
'exists' => $exists);
if ($event->lat && $event->lon) {
foreach (array_combine (explode (',', $event->lat), explode (',', $event->lon)) as $lat => $lon) {
$location = '('.$lat.'|'.$lon.')';
$LocationsEvents [$location][$dn_day][$pageIdAt] = $dayEvents [$pageIdAt];
$locations .= ','.$location;
}
} elseif ($event->where) {
$location = $event->where;
$LocationsEvents [$location][$dn_day][$pageIdAt] = $dayEvents [$pageIdAt];
$locations .= ','.$location;
}
// YYY sauf répétition de jours
return array ($LocationsEvents, $dayEvents, $locations);
}
function formatDayEventsBubble ($dn_day, $dayEvents) {
$content = '';
$this->scheduleRoot->resetOddEven ();
foreach ($dayEvents as $pageIdAt => $values) {
$line = '';
sort ($values['logo']);
foreach ($values['logo'] as $logoId)
$line .= '<img src="'.ml ($logoId, array ('cache'=>$_REQUEST['cache'], 'w'=>20)).'" width="20"/> ';
if ($values['at'])
$line .= $values['at']. ' ';
$line .= $values['what'];
if ($values['where'])
$line .= ' - '.$this->makeWhereString ($values['where']);
$line .= ' : '.$values['title'];
if ($values['exists'])
$line = '<a href="?id='.$values['pageId'].'">'.$line.'</a>';
$content .= '<div class="'.$this->scheduleRoot->getOddEven ().'">'.$line.'</div>'.NL;
$this->scheduleRoot->switchOddEven ();
}
if (!$content)
return '';
return '<div class="date">'.date ($this->scheduleRoot->currentDateFormat['prettyPrint'], $dn_day).'</div>'.$content;
}
function getDayBubble ($dn_day, $dayEvents) {
uasort ($dayEvents, 'cmpScheduleInDay');
$this->scheduleRoot->resetOddEven ();
$content = $this->formatDayEventsBubble ($dn_day, $dayEvents);
if (!$content)
return '';
return '<div class="bubble '.$this->getConf ('bubblePosition').'Bubble">'.$content.'</div>';
}
// ============================================================
function getCityBubble ($LocationsEvents) {
$content = '';
// XXX uasort ($dayEvents, 'cmpScheduleInCities');
foreach ($LocationsEvents as $location => $datedEvents) {
$locationContent = '';
foreach ($datedEvents as $dn_day => $dayEvents)
$locationContent .= $this->formatDayEventsBubble ($dn_day, $dayEvents);
if ($locationContent)
$content .= '<div class="cityBubble" location="'.$location.'"><div class="bubble '.$this->getConf ('bubblePosition').'Bubble">'.$locationContent.'</div></div>';
}
return $content;
}
// ============================================================
/* Print schedule as a matrix or list */
function printScheduleList ($mapId) {
if ($this->isAdmin ()) {
echo '<div><form>';
foreach (array ('clear', 'clearAll') as $action)
echo '<input value="'.$this->getLang ($action).'" onclick="javascript:scheduleClearCache (\''.$action.'\', \''.$this->nameSpace.'\')" type="button">';
echo '</form></div>';
}
ptln ('<div class="schedule">');
if ($this->printProp || $this->printForm)
$this->printScheduleInputForm ($mapId);
if ($this->printCtrl)
ptln ('</div>'.NL.
'<div class="schedule">'.NL.
' <form method="POST" action="'.$_SERVER['PHP_SELF'].'">'.NL.
' <input type="hidden" name="schd[ns]" value="'.$this->nameSpace.'"/>'.NL.
' <input type="hidden" name="id" value="'.$_REQUEST['id'].'" />');
ptln (' <table class="long" onMouseOut="javascript:scheduleHighlightEvent (null, null)">');
$this->printScheduleListHead ();
if ($this->isAdmin ())
$this->printScheduleListContent ($this->allProposals, true);
$this->printScheduleListContent ($this->allSchedules);
$this->printScheduleDeleteForm ();
ptln (' </table>');
if ($this->printCtrl)
ptln (' </form>');
ptln ('</div>');
}
// ============================================================
/* Print schedule head list */
function printScheduleListHead () {
global $conf;
ptln (' <thead>'.NL.
' <tr>'.NL.
' <th class="when" rowspan="2">'.
($this->isShow ?
('<a href="?id='.$this->nameSpace.':'.$conf ['start'].'" rel="nofollow" class="wikilink1">'.
$this->getLang ('allDates').'</a>') :
$this->getLang ('when')).'</th>'.NL.
' <th class="what">'.$this->getLang ('what').'</th>'.NL.
' <th class="where">'.$this->getLang ('where').'</th>'.NL.
' <th class="suject">'.$this->getLang ('title').'</th>'.NL.
' </tr>'.NL.
' <tr>'.NL.
' <th class="audience">'.$this->getLang ('audience').'</th>'.NL.
' <th class="by">'.$this->getLang ('proposedBy').'</th>'.NL.
' <th class="repeat">');
if ($this->printCtrl)
ptln ('<input class="button" type="button" onclick="scheduleSwitchSelection(this.form)" value="'.$this->getLang ('inverted').'"/>');
ptln ('</th>'.NL.
' </tr>'.NL.
' </thead>');
}
// ============================================================
/* Print schedule line list */
function printScheduleLineEvent ($pageId, $lineVals, $even, $prop = false) {
$ns = $this->nameSpace;
$event = $lineVals['event'];
$propClass = $prop ? ' proposal' : '';
$day = $this->scheduleRoot->ds2df ($event->syncStart ? $event->syncStart : $event->from);
$overEvent=' onMouseOver="javascript:scheduleHighlightEvent (\''.$day.'\', \''.$this->getLocationsFromEvent ($event).'\')"';
ksort ($lineVals['member']);
ptln (' <tr class="'.$this->scheduleRoot->getOddEven ().' '.$lineVals ['class'].$propClass.'" '.$overEvent.'>'.NL.
' <td class="when" rowspan="2">');
if ($prop)
ptln ('<i>proposition</i><br/>');
ptln ($day.(($event->syncStart || ('' == $event->to)) ? '' : '<br/>'.NL.$this->scheduleRoot->ds2df ($event->to)).('' == $event->at ? '' : '<br/>'.NL.$event->at).'</td>'.NL.
' <td class="what">'.$event->what.'</td>'.NL.
' <td class="where">'.$this->makeWhereString ($event->where).'</td>'.NL.
' <td class="title"><a class="'.$lineVals['css'].'" href="?id='.$pageId.'">'.$event->title.'</a></td>'.NL.
' </tr>'.NL.
' <tr class="'.$this->scheduleRoot->getOddEven ().' '.$lineVals ['class'].$propClass.'" '.$overEvent.'>'.NL.
' <td class="audience">'.$event->audience.'</td>'.NL.
' <td class="proposedBy">');
if ($this->printCtrl) {
ptln ($this->scheduleRoot->scheduleShared[$event->shared]);
if (!$prop && !$lineVals['exists'] && $this->isAMemberOf (array_keys ($lineVals['member']))) {
// petite baguette magique de création
$id = reset (array_values($lineVals['member']));
ptln ('<a href="?id='.$_REQUEST['id'].'&schd[id]='.$id.'&schd[ns]='.$ns.'&schd[pageId]='.$pageId.'&schd[action]='.$this->getLang ('created').'">'.
' <img src="'.$this->scheduleRoot->wizardIconUrl.'"/></a>');
}
}
foreach ($lineVals['member'] as $member => $id) {
echo '<span style="white-space: nowrap;">';
if ($this->printCtrl && $this->isMember ($member)) {
// suppression ou édition pour un membre
ptln ('<input type="checkbox" name="schd[idl][]" value="'.$id.'"/> '.
'<a href="?id='.$_REQUEST['id'].'&schd[id]='.$id.'&schd[ns]='.$ns.'&schd[action]='.$this->getLang ('selected').'">'.
'<img src="'.$this->scheduleRoot->editIconUrl.'"/></a>');
}
$logoId = $this->scheduleRoot->groupsDir.':'.$member.':'.$this->scheduleRoot->iconName;
// YYY
ptln ('
<a href="/'.$this->scheduleRoot->groupsDir.':'.$member.'/"><img src="'.ml ($logoId, array ('cache'=>$_REQUEST['cache'], 'w'=>$this->scheduleRoot->iconWidth)).'" width="'.$this->scheduleRoot->iconWidth.'"/></a></span> ');
}
ptln ('</td>'.NL.
' <td class="repeat">');
if ($event->repeatFlag)
ptln ('<img src="'.$this->scheduleRoot->repeatIconUrl.'" /> '.$this->makeRepeatString ($event, false));
ptln ('</td>'.NL.
' </tr>');
}
// ============================================================
function makePrettyAt ($at) {
if (!$at)
return '';
if (preg_match ("#(?<from>[^-]*)-(?<to>[^-]*)#", $at, $dumy))
return ' '.$this->getLang ('fromHour').' **'.$dumy ['from'].'** '.$this->getLang ('toHour').' **'.$dumy ['to'].'**';
return ' '.$this->getLang ('at').' **'.$at.'**';
}
function makeListPlaceForMap ($schedule) {
global $scheduleInseeCities;
$result= '';
$cities = explode (',', $schedule->where);
$lats = explode (',', $schedule->lat);
$lons = explode (',', $schedule->lon);
$addrs = explode ('|', $schedule->addr);
$unknownAddr = false;
for ($i = 0; $i < count ($cities); $i++) {
if (!isset ($addrs [$i]))
$unknownAddr = true;
$result .=
$cities[$i].' | '.
(isset ($lats [$i]) ? $lats [$i] : '').' | '.
(isset ($lons [$i]) ? $lons [$i] : '').' | '.
(isset ($addrs [$i]) ? $addrs [$i] : '').
NL;
}
if ($unknownAddr)
$result .= '<wrap todo>Les coordonnées par défaut correspondent aux centres-villes !</wrap>'.NL;
return $result;
}
// ============================================================
/* Create a natural langage string for cities zipcode */
function makeWhereString ($where) {
global $scheduleInseeCities;
$result = array ();
foreach (explode (',', $where) as $zip)
$result[] = (isset ($scheduleInseeCities[$zip]) ?
$scheduleInseeCities[$zip][0] :
($this->showOldValues ? '<b>'.$zip.'</b>' : $zip));
return implode (',', array_unique ($result));
}
// ============================================================
/* Create a natural langage string to formulate repeat event */
function makeRepeatString ($event, $bold = false) {
$orderedFormat = $this->getLang ('orderedFormat');
$rt = $this->getLang ('repeatType');
$result = '';
switch ($event->repeatType) {
case 'day' :
return $this->getLang ('from').' '.$this->scheduleRoot->ds2ln ($event->from, $bold).' '.$this->getLang ('to').' '.$this->scheduleRoot->ds2ln ($event->to, $bold);
break;
// pour gagner du temps
case 'week' :
foreach (array_keys ($this->getLang ('days')) as $idd => $dayName)
$result .= in_array ($idd, explode ('|', $event->weekDays)) ? $dayName.' ' : '';
break;
case 'dayMonth' :
$dayNames = array_keys ($this->getLang ('days'));
// XXX pb OVH => utilisation de tableau au lieu de fonction
// $result .= $f ($event->weekRank+1).' '.$d [$event->dayInWeek].' ';
$result .= $orderedFormat [$event->weekRank+1].' '.$dayNames [$event->dayInWeek].' ';
break;
case 'dateMonth' :
// XXX pb OVH => utilisation de tableau au lieu de fonction
// $result .= $f ($event->dayRank).' ';
$result .= $orderedFormat [$event->dayRank].' ';
break;
case 'year' :
// XXX le Ie jour du Je mois
preg_match ("#(?<Y>[0-9]{4})(?<m>[0-9]{2})(?<d>[0-9]{2})#", $event->from, $dt_from);
$dn_from = $this->scheduleRoot->dt2dn ($dt_from);
$result .= date ($this->scheduleRoot->currentDateFormat ['dayMonth'], $dn_from).' ';
}
$result .= $this->getLang ('all').' ';
if ($event->repeat > 1)
$result .= $event->repeat.' ';
$result .= $rt[$event->repeatType];
return $result;
}
// ============================================================
/* Add a schedule line list in array for futur print */
function addEventTab (&$tab, $event, $when, $pageId, $eventClass, $exists, $cssLink) {
if (!$tab [$when])
$tab [$when] = array ();
if ($tab [$when][$pageId])
$tab [$when][$pageId]['member'][$event->member] = $event->id;
else
$tab [$when][$pageId] =
array ('member' => array ($event->member => $event->id), 'event' => $event, 'class' => $eventClass, 'exists' => $exists, 'css' => $cssLink);
}
// ============================================================
/* Print all schedule line list */
function printScheduleListContent ($allSchedules, $prop = false) {
$linesTab = array ();
$repeatTab = array ();
if ($this->after) {
preg_match ("#(?<Y>[0-9]{4})(?<m>[0-9]{2})(?<d>[0-9]{2})#", $this->after, $dt_start);
$dn_start = $this->scheduleRoot->dt2dn ($dt_start);
}
foreach ($allSchedules as $event) {
// XXX même filtre pour printScheduleCalendar ?
if ($this->before && strcmp ($event->from, $this->before) > 0)
continue;
// XXX repeat le même jour => calcul
if ($this->date && (strcmp ($event->from, $this->date) > 0 ||
strcmp (('' != $event->to ? $event->to : $event->from), $this->date) < 0))
continue;
if ($this->after &&
strcmp (('' != $event->to ? $event->to : $event->from), $this->after) < 0)
continue;
if ($this->max && $line > $this->max)
break;
$continue = false;
if ($this->filters)
foreach ($this->filters as $name => $values) {
if (in_array ($name, $this->scheduleRoot->filterNames) && !in_array ($event->$name, $values)) {
$continue = true;
break;
} elseif (in_array ($name, array_keys ($this->scheduleRoot->filterNames))) {
$trueName = $this->scheduleRoot->filterNames[$name];
if (in_array ($event->$trueName, $values)) {
$continue = true;
break;
}
}
}
if ($continue)
continue;
$pageId = $this->scheduleRoot->getPageId ($event);
resolve_pageid ($this->nameSpace, $pageId, $exists);
$cssLink = $exists ? 'wikilink1' : 'wikilink2';
$eventClass = 'cat_'.preg_replace ("/\s/", '', htmlspecialchars (strtolower ($this->scheduleRoot->scheduleWhat [$event->what])));
$when = $event->from.'-'.$event->at.'-'.$event->to;
if ($event->repeatFlag) {
if (!$this->after || strcmp ($event->from, $this->after) > 0)
$event->syncStart = $event->from;
else {
// cas ou il faut déplacer le début de la répétition (on ne déplace si la 1re occurance est après le début de la fenêtre)
preg_match ("#(?<Y>[0-9]{4})(?<m>[0-9]{2})(?<d>[0-9]{2})#", $event->from, $dt_from);
$dn_day = $dn_from = $this->scheduleRoot->dt2dn ($dt_from);
// on déplace sur la 1re occurance
switch ($event->repeatType) {
// chercher le 1er évènement après 'after'
case 'day' :
$step = 86400 * $event->repeat;
$dn_day += ceil (($dn_start - $dn_from) / $step) * $step;
break;
case 'week' :
$dn_startWeek = mktime (0, 0, 0, date ('m', $dn_from), date ('d', $dn_from) - date ('w', $dn_from), date ('Y', $dn_from));
$step = 86400 * 7 * $event->repeat;
$dn_startWeek += floor (($dn_start - $dn_startWeek) / $step) * $step;
// au pire start commence après les jours répétés dans la semaine
for ($i = 0; $i < 2; $i++, $dn_startWeek += $step) {
foreach (explode ('|', $event->weekDays) as $idd) {
$dn_day = $dn_startWeek + $idd * 86400;
if ($dn_day >= $dn_start && $dn_day >= $dn_from) {
break 2;
}
}
}
break;
case 'dayMonth' :
case 'dateMonth' : {
$dn_startMonth = mktime (0, 0, 0, date ('m', $dn_from), 1, date ('Y', $dn_from));
$nbMonth = floor ((date ('m', $dn_start) + date ('Y', $dn_start)*12 - (date ('m', $dn_from) + date ('Y', $dn_from)*12))/$event->repeat)*$event->repeat;
$dn_startMonth = mktime (0, 0, 0, date ('m', $dn_startMonth) + $nbMonth, 1, date ('Y', $dn_startMonth));
for ($i = 0; $i < 2; $i++, $dn_startMonth = mktime (0, 0, 0, date ('m', $dn_startMonth) + $event->repeat, 1, date ('Y', $dn_startMonth))) {
$dn_day = $dn_startMonth;
if ($event->repeatType == 'dateMonth')
// XXX pb si moins de jour dans le mois
$dn_day = mktime (0, 0, 0, date ('m', $dn_startMonth), $event->dayRank, date ('Y', $dn_startMonth));
else {
$delta = $event->dayInWeek - date ('w', $dn_startMonth);
if ($delta < 0)
$delta += 7;
$delta += 7 * $event->weekRank;
// XXX pb si moins de jour dans le mois
$dn_day = mktime (0, 0, 0, date ('m', $dn_startMonth), $delta+1, date ('Y', $dn_startMonth));
}
if ($dn_day >= $dn_start && $dn_day >= $dn_from)
break;
}
break;
}
case 'year' :
$dayInmonth = date ('j', $dn_from);
$monthInYear = date ('n', $dn_from);
$startYear = date ('Y', $dn_start) - (date ('Y', $dn_start) - date ('Y', $dn_from)) % $event->repeat;
for ($i = 0; $i < 2; $i++, $startYear += $event->repeat) {
$dn_day = mktime (0, 0, 0, $monthInYear, $dayInmonth, $startYear);
if ($dn_day >= $dn_start && $dn_day >= $dn_from)
break;
}
break;
}
$ds_day = date ('Ymd', $dn_day);
if ($this->before && strcmp ($ds_day, $this->before) > 0)
continue;
if ($this->date && strcmp ($ds_day, $this->date) != 0)
continue;
$event->syncStart = $ds_day;
$when = $ds_day.'-'.$event->at.'-'.$event->to;
}
}
if ($this->repeatGrouped && $event->repeatFlag)
schedules::addEventTab ($repeatTab, $event, $when, $pageId, $eventClass, $exists, $cssLink);
else
schedules::addEventTab ($linesTab, $event, $when, $pageId, $eventClass, $exists, $cssLink);
}
ksort ($repeatTab);
ksort ($linesTab);
$line = 1;
foreach ($repeatTab as $when) {
foreach ($when as $pageId => $lineVals) {
schedules::printScheduleLineEvent ($pageId, $lineVals, $even, $prop);
$this->scheduleRoot->switchOddEven ();
$line++;
}
}
foreach ($linesTab as $when) {
foreach ($when as $pageId => $lineVals) {
schedules::printScheduleLineEvent ($pageId, $lineVals, $even, $prop);
$this->scheduleRoot->switchOddEven ();
$line++;
}
}
if ($line < 1)
echo '
<tr class="'.$this->scheduleRoot->getOddEven ().'"><td colspan="6">'.$this->getLang ('noEvent').'</td></tr>';
}
// ============================================================
/* Print delete button in form */
function printScheduleDeleteForm () {
if (!$this->printCtrl)
return;
echo '
<tr>
<th colspan="2"></th>
<th><input type="submit" name="schd[action]" value="'.$this->getLang ('remove').'"/></th>
<th></th>
</tr>';
}
// ============================================================
/* Print add event form */
function printRepeatForm () {
$repeat = ($this->defaultSchedule->repeat > 1) ? $this->defaultSchedule->repeat : 1;
ptln('
<table>
<tr>
<td colspan="8">'.$this->getLang ('all').' <input class="repeat" name="schd[repeat]" type="text" value="'.$repeat.'"/>
<select name="schd[repeatType]" onChange="scheduleUpdateRepeatType (this)">
');
foreach ($this->getLang ('repeatType') as $idrt => $repeatType) {
$selected = ($this->defaultSchedule->repeatType == $idrt) ? ' selected="true"' : '';
ptln (' <option value="'.$idrt.'"'.$selected.'>'.$repeatType.'</option>'.NL);
}
ptln ('
</select>
</td>
</tr><tr>
<td rowspan="2">'.$this->getLang ('each').'</td>
');
$disabled = ($this->defaultSchedule->repeatType !== "week") ? ' disabled="true"' : '';
$eventWeekDays = explode ("|", $this->defaultSchedule->weekDays);
$checkbox = "";
$dayNames = $this->getLang ('days');
foreach (array_values ($dayNames) as $idd => $dayAbrv) {
ptln ('
<td>'.$dayAbrv.'</td>
');
$selected = in_array ($idd, $eventWeekDays) ? ' checked="true"' : '';
$checkbox .= ' <td><input type="checkbox" name="schd[weekDays][]" onclick="scheduleUpdateWeekDays (this)" value="'.$idd.'"'.$selected.$disabled.'/></td>'.NL;
}
$disabled = ($this->defaultSchedule->repeatType !== "dayMonth") ? ' disabled="true"' : '';
ptln ('
</tr><tr>
'.$checkbox.'
</tr><tr>
<td colspan="8">
<select name="schd[weekRank]"'.$disabled.'>'
);
$orderedFormat = $this->getLang ('orderedFormat');
for ($week = 0; $week < 5; $week++) {
$selected = ($week == $this->defaultSchedule->weekRank) ? ' selected="true"' : '';
// XXX pb OVH => utilisation de tableau au lieu de fonction
// echo '<option value="'.$week.'"'.$selected.'>'.$f ($week+1).'</option>'.NL;
ptln (' <option value="'.$week.'"'.$selected.'>'.$orderedFormat [$week+1].'</option>'.NL);
}
ptln ('
</select>
<select name="schd[dayInWeek]"'.$disabled.'>
');
foreach (array_keys ($dayNames) as $idw => $week) {
$selected = ($idw == $this->defaultSchedule->dayInWeek) ? ' selected="true"' : '';
ptln (' <option value="'.$idw.'"'.$selected.'>'.$week.'</option>');
}
$disabled = ($this->defaultSchedule->repeatType !== "dateMonth") ? ' disabled="true"' : '';
ptln ('
</select>
<select name="schd[dayRank]"'.$disabled.'>
');
for ($dayRank = 1; $dayRank < 32; $dayRank++) {
$selected = ($dayRank == $this->defaultSchedule->dayRank) ? ' selected="true"' : '';
ptln (' <option value="'.$dayRank.'"'.$selected.'>'.$orderedFormat [$dayRank].'</option>'.NL);
}
ptln ('
</select>
</td>
</tr>
</table>');
}
// ============================================================
function printScheduleInputForm ($mapId) {
if (!($this->printForm || $this->printProp))
return;
$from = (!$this->defaultSchedule->from && isset ($_REQUEST["schd"]["date"])) ?
$_REQUEST["schd"]["date"] :
$this->scheduleRoot->ds2df ($this->defaultSchedule->from);
ptln (' <div class="scheduleTabForm">'.NL.
' <p>'.$this->getLang ($this->printProp ? 'proposedEvent' : 'addEvent').'</p>'.NL. // XXX getLang
' <ul>'.NL.
' <li><a class="warningPlace" href="#scheduleTabForm-0">1) '.$this->getLang ('who').'</a></li>'.NL.
' <li><a class="warningPlace" href="#scheduleTabForm-1">2) '.$this->getLang ('what').'</a></li>'.NL.
' <li><a class="warningPlace" href="#scheduleTabForm-2">3) '.$this->getLang ('where').'</a></li>'.NL.
' <li><a class="warningPlace" href="#scheduleTabForm-3">4) '.$this->getLang ('when').'</a></li>'.NL.
' <li><a class="warningPlace" href="#scheduleTabForm-4">5) '.$this->getLang ('validation').'</a></li>'.NL.
' </ul>'.NL.
' <form class="scheduleMiscForm">'.NL.
' <div id="scheduleTabForm-0">'.NL.
' <div>'.NL.
' <div class="warningPlace"></div><select name="schd[audience]" onChange="scheduleCheckInputs ()">'.NL);
foreach ($this->scheduleRoot->scheduleAudience as $audience => $label) {
$selected = ($audience == $this->defaultSchedule->audience) ? ' selected="true" ' : '';
ptln (' <option value="'.$audience.'"'.$selected.'>'.$label.'</option>'.NL);
}
ptln (' </select>'.NL.
' <select name="schd[shared]" onChange="scheduleSharedEvent (this.form)">'.NL);
foreach (array (false, true) as $sharedVal) {
$selected = ($sharedVal == $this->defaultSchedule->shared) ? ' selected="true" ' : '';
ptln (' <option value="'.$sharedVal.'"'.$selected.'>'.$this->scheduleRoot->scheduleShared[$sharedVal].'</option>'.NL);
}
ptln (' </select>'.NL.
' <div class="warningPlace"></div><select class="members" name="schd[member]"'.($this->defaultSchedule->shared ? ' multiple="true"' : "").' size="'.($this->defaultSchedule->shared == 1 ? 9 : 1).'" onChange="scheduleCheckInputs ()">');
$availableGroup = ($this->isAdmin () || $this->printProp)? $this->allGroups : $this->userGroups;
$sharedMembers = $this->defaultSchedule->prop ?
explode (",", $this->defaultSchedule->member) :
$this->getMembersSharedEvents ($this->defaultSchedule);
ptln (' <option value="">'.$this->getLang ('memberChoice').'</option>'.NL);
foreach ($availableGroup as $member) {
$selected = in_array ($member, $sharedMembers) ? ' selected="true" ' : '';
ptln (' <option value="'.$member.'"'.$selected.'>'.$member.'</option>'.NL);
}
ptln (' </select>'.NL.
' </div>'.NL.
' </div>'.NL.
' <div id="scheduleTabForm-1">'.NL.
' <div class="warningPlace"></div><select name="schd[what]" onChange="scheduleCheckInputs ()" >'.NL.
' <option value="">'.$this->getLang ('eventTypeChoice').'</option>'.NL);
foreach (array_keys ($this->scheduleRoot->scheduleWhat) as $what) {
$selected = ($what == $this->defaultSchedule->what) ? ' selected="'.$what.' '.$this->defaultSchedule->what.'" ' : '';
ptln (' <option value="'.$what.'"'.$selected.'>'.$what.'</option>'.NL);
}
ptln (' </select>'.NL.
' <input class="title" name="schd[title]" type="text" value="'.$this->defaultSchedule->title.'" placeholder="'.$this->getLang ('titlePH').'" onChange="scheduleCheckInputs ()"/>'.NL.
' <p>'.NL.
' '.$this->getLang ('lead').':<br/>'.NL.
' <textarea class="paper" name="schd[lead]" placeholder="'.$this->getLang ('leadPH').'">'.$this->defaultSchedule->lead.'</textarea>'.NL.
' </p><p>'.NL.
' '.$this->getLang ('posterURL').':<br/>'.NL.
' <input class="poster" name="schd[posterURL]" type="text" value="'.$this->defaultSchedule->posterURL.'" placeholder="'.$this->getLang ('posterPH').'"/>'.NL.
' </p><p>'.NL.
' '.$this->getLang ('paperURL').':<br/>'.NL.
' <input class="paper" name="schd[paperURL]" type="text" value="'.$this->defaultSchedule->paperURL.'" placeholder="'.$this->getLang ('paperPH').'"/>'.NL.
' </p><p>'.NL.
' '.$this->getLang ('remark').':<br/>'.NL.
' <textarea class="paper" name="schd[remark]" placeholder="'.$this->getLang ('remarkPH').'">'.$this->defaultSchedule->remark.'</textarea>'.NL.
' </p><p>'.NL.
' '.$this->getLang ('rate').':<br/>'.NL.
' <input class="rate" name="schd[rate]" type="text" value="'.$this->defaultSchedule->rate.'" placeholder="'.$this->getLang ('ratePH').'"/>'.NL.
' </p>'.NL.
' </div>'.NL.
' </form>'.NL.
' <div id="scheduleTabForm-2">'.NL.
' <form class="scheduleCitiesForm insee">'.NL.
' <div>'.NL.
' <div id="'.$mapId.'" class="scheduleMap scheduleMapForm"></div>'.NL.
' <div class="ui-widget">'.NL.
' <div><ul class="cities warningPlace">'.NL);
if ($this->defaultSchedule->where) {
global $scheduleInseeCities;
$cities = explode (',', $this->defaultSchedule->where);
$lats = explode (',', $this->defaultSchedule->lat);
$lons = explode (',', $this->defaultSchedule->lon);
$addrs = explode ('|', $this->defaultSchedule->addr);
for ($i = 0; $i < count ($cities); $i++) {
$insee = $cities[$i];
$cityName =
isset ($scheduleInseeCities [$insee]) ?
$scheduleInseeCities [$insee][0] :
$insee;
ptln (' <li onclick="scheduleSelectCity (this)" insee="'.$insee.'" lat="'.
(isset ($lats [$i]) ? $lats [$i] : "").'" lon="'.
(isset ($lons [$i]) ? $lons [$i] : "").'"><img class="checked" src="'.
$this->scheduleRoot->emptyIconUrl.'" onclick="scheduleRemoveCity (this)"/>'.
'<span class="addresse">'.(isset ($addrs [$i]) ? str_replace ('\\\\', '<br/>', str_replace ('~br~', '<br/>', $addrs [$i])) : "").'</span> '.
'<span class="city">'.$cityName.'</span></li>');
}
}
ptln (' </ul></div>'.NL.
' <label>'.$this->getLang ('city').' :<br/></label><input name="city" type="text" placeholder="'.$this->getLang ('cityPH').'"/>'.NL.
' <span class="wrap_tip ">'.$this->getLang ('enterTip').'</span>'.NL.
' <label>'.$this->getLang ('addresse').' :<br/></label><input name="addr" type="text" placeholder="'.$this->getLang ('addrPH').'"/>'.NL.
' <span class="wrap_tip ">'.$this->getLang ('enterTip').'</span>'.NL.
' </div>'.NL.
' </div>'.NL.
' </form>'.NL);
if ($this->isAdmin ())
ptln (' <div>'.NL.
'<input type="button" value="'.$this->getLang ('add').'" onClick="javascript:scheduleAddInsee ()" />'.NL.
'<input type="button" value="'.$this->getLang ('remove').'" onClick="javascript:scheduleRemoveInsee ()" />'.NL.
'<input type="button" value="'.$this->getLang ('test').'" onClick="javascript:scheduleTestInsee ()" />'.NL.
'</div>'.NL);
ptln (' </div>'.NL.
' <form class="scheduleFinalForm" method="POST" action="'.$_SERVER["PHP_SELF"].'">'.NL.
' <div id="scheduleTabForm-3">'.NL.
' <p>'.NL.
$this->getLang ('from').' <input class="date" id="scheduleFrom" name="schd[from]" type="text" value="'.$from.'" placeholder="'.$this->getLang ('datePH').'" onChange="scheduleCheckInputs ()" /> '.
$this->getLang ('to').' <input class="date" name="schd[to]" type="text" value="'.$this->scheduleRoot->ds2df ($this->defaultSchedule->to).'" placeholder="'.$this->getLang ('datePH').'"/></p><p>'.
$this->getLang ('at').' <input class="hour" name="schd[at]" type="text" value="'.$this->defaultSchedule->at.'" placeholder="'.$this->getLang ('hourPH').'"/></p>');
$this->printRepeatForm ();
ptln (' </div>'.NL.
' <div id="scheduleTabForm-4">'.NL.
' <p>'.NL.
' <input type="hidden" name="schd[ns]" value="'.$this->nameSpace.'"/>'.NL.
' <input type="hidden" name="id" value="'.$_REQUEST["id"].'" />'.NL);
if ($this->printForm) {
if ($this->defaultSchedule->id) {
ptln ('<input type="hidden" name="schd[id]" value="'.$this->defaultSchedule->id.'"/>');
if (!$this->defaultSchedule->prop) {
if (count ($this->getMembersSharedEvents ($this->defaultSchedule)) > 1)
ptln ('<input type="submit" name="schd[action]" value="'.$this->getLang ('modifyAll').'"/>');
ptln ('<input type="submit" name="schd[action]" value="'.$this->getLang ('modify').'"/> ');
}
}
ptln ('<input type="submit" name="schd[action]" value="'.$this->getLang ($this->defaultSchedule->prop ? 'valid' : 'add').'"/>');
}
if ($this->printProp) {
ptln ('<input type="submit" name="schd[action]" value="'.$this->getLang ('prop').'"/> ');
if ($captcha =& plugin_load ('helper', 'captcha'))
ptln ($captcha->getHTML ());
}
ptln (' </p>'.NL.
' </div>'.NL.
' </form>'.NL.
' <div id="scheduleHelp">'.NL.
' <a href="#">Aide</a>'.NL.
' <div>'.NL.
' <div class="vshare__center">'.NL.
' <!--[if !IE]> --><object type="application/x-shockwave-flash" data="http://www.dailymotion.com/swf/x10xcw7_" height="350" width="623"><!-- <![endif]-->'.NL.
' <!--[if IE]><object width="623" height="350" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"> <param name="movie" value="http://www.dailymotion.com/swf/x10xcw7_" /><!--><!-- -->'.NL.
' <param name="FlashVars" value="">'.NL.
' </object>'.NL.
' <!-- <![endif]-->'.NL.
' </div>'.NL.
' </div>'.NL.
' </div>'.NL.
' </div>'.NL);
}
// ============================================================
function resetAdminNotification () {
$this->lastNotificationReset = date ('YmdHis');
$this->scheduleRoot->writeConfig ($this);
}
function adminNotification () {
if ($this->lastNotification > $this->lastNotificationReset)
return;
global $auth;
$users = $auth->retrieveUsers ();
foreach ($users as $user => $userinfo) {
$mailSubject = $this->getLang ('notifySubject');
$mailContent = $this->getLang ('notifyContent');
if (in_array (trim ($this->getConf ('adminGroup')), $userinfo ['grps'])) {
mail_send ($userinfo['mail'], $mailSubject, $mailContent);
}
}
$this->lastNotification = date ('YmdHis');
$this->scheduleRoot->writeConfig ($this);
}
// ============================================================
}