466 lines
20 KiB
PHP
466 lines
20 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
|
|
*
|
|
* $df_ : 31/12/2000
|
|
* $ds_ : 20001231
|
|
* $dn_ : 978217200
|
|
* $dt_ : array ("Y" => 2000, "m" => 12, "d" => "31)
|
|
*/
|
|
if (!defined ('DOKU_INC'))
|
|
define ('DOKU_INC', realpath (dirname (__FILE__).'/../../../').'/');
|
|
if (!defined ('DOKU_PLUGIN'))
|
|
define ('DOKU_PLUGIN', DOKU_INC.'lib/plugins/');
|
|
|
|
function cmpScheduleConfig ($a, $b) {
|
|
return ($a['nameSpace'] < $b['nameSpace']) ? -1 : 1;
|
|
}
|
|
|
|
// ============================================================
|
|
// admin class
|
|
class scheduleRoot {
|
|
|
|
// ============================================================
|
|
// Config attributs
|
|
// ============================================================
|
|
var $cacheRootDir; // root cache directory
|
|
var $dataRootDir; // root data directory
|
|
|
|
var $scheduleGroup; // group who can display and fill form
|
|
var $groupsDir; // pages groups directories
|
|
var $scheduleDir; // schedule pages groups directories
|
|
var $sharedDir; // schedule directory for shared events
|
|
var $scheduleWhat = array (); // set of legal "what"
|
|
var $scheduleAudience = array (); // set of legal "audience"
|
|
var $iconName; // group icon name
|
|
var $iconWidth; // group icon width
|
|
// lang
|
|
var $scheduleShared = array (); // notshared/shared
|
|
var $currentDateFormat;
|
|
|
|
// ============================================================
|
|
// Constant attributs $this->scheduleRoot->
|
|
// ============================================================
|
|
//var $imagesUrlDir = '/lib/plugins/schedule/images/'; // DOKU_REL
|
|
var $wizardIconUrl = '/lib/plugins/schedule/images/wizard.png'; // $this->imagesUrlDir
|
|
var $editIconUrl = '/lib/plugins/schedule/images/edit.png';
|
|
var $repeatIconUrl = '/lib/plugins/schedule/images/repeat.png';
|
|
var $emptyIconUrl = '/lib/plugins/schedule/images/empty.png';
|
|
|
|
var $oldConfigFile = "config.xml"; // old file config name
|
|
var $configFile = "cfg.xml"; // file config name
|
|
var $mbrPrefix = "mbr-"; // member prefix file name
|
|
var $propFile = "prop.xml"; // member prefix file name
|
|
var $configAttributsName = array ("nameSpace", "lastNotification", "lastNotificationReset");
|
|
// scheduleDir == NS ?
|
|
var $dateFormat = array ("dmY" => array ("shortScan" => "(?<d>[0-9]{1,2})[ /-](?<m>[0-9]{1,2})[ /-](?<Y>[0-9]{1,2})",
|
|
"longScan" => "(?<d>[0-9]{1,2})[ /-](?<m>[0-9]{1,2})[ /-](?<Y>[0-9]{4})",
|
|
"fieldName" => array ("d", "m", "Y"),
|
|
"prettyPrint" => "d/m/Y",
|
|
"dayMonth" => "d/m"),
|
|
|
|
"mdY" => array ("shortScan" => "(?<m>[0-9]{1,2})[ /-](?<d>[0-9]{1,2})[ /-](?<Y>[0-9]{1,2})",
|
|
"longScan" => "(?<m>[0-9]{1,2})[ /-](?<d>[0-9]{1,2})[ /-](?<Y>[0-9]{4})",
|
|
"fieldName" => array ("m", "d", "Y"),
|
|
"prettyPrint" => "m/d/Y",
|
|
"dayMonth" => "m/d"));
|
|
var $oddEvenValues = array ("odd", "even");
|
|
var $scheduleRequestAttributsName = array ("id", "audience", "shared",
|
|
"what", "title", "lead", "posterURL", "paperURL", "remark", "rate",
|
|
"where", "lon", "lat", "addr",
|
|
"from", "to", "at",
|
|
"repeat", "repeatType", "weekRank", "dayInWeek", "dayRank",
|
|
"user");
|
|
var $scheduleSaveAttributsName;
|
|
var $filterNames = array ("noMember" => "member",
|
|
"noWhat" => "what",
|
|
"NoAudience" => "audience");
|
|
|
|
|
|
// ============================================================
|
|
// Transcient attributs
|
|
// ============================================================
|
|
var $message = array (); // messages to display : "notify" =>, "info" =>, "success" =>, "error" =>
|
|
var $plugin; // link to wiki plugin inforation (conf, lang, ...)
|
|
var $isAdmin; // if user member of schedule adminGroup
|
|
var $oddEven = 0; // background color for table lines
|
|
|
|
// ============================================================
|
|
// Util
|
|
// ============================================================
|
|
/* messages container to be display before plugin */
|
|
function message ($type, $text) {
|
|
if (isset ($this->message[$type]))
|
|
$this->message[$type] .= '<br/>'.NL;
|
|
$this->message[$type] .= $text;
|
|
}
|
|
function startMessage ($type, $text) {
|
|
if (isset ($this->message[$type]))
|
|
$this->message[$type] = '<br/>'.NL.$this->message[$type];
|
|
$this->message[$type] = $text.$this->message[$type];
|
|
}
|
|
/* debug messages for admin only */
|
|
function debug ($text) {
|
|
global $INFO;
|
|
// XXX
|
|
if (isset ($INFO['userinfo'] ['grps']) && in_array ('admin', $INFO ['userinfo'] ['grps']))
|
|
$this->message ('notify', '<pre>'.$text.'</pre>');
|
|
}
|
|
/* Change date format from array to number */
|
|
function dt2dn ($dt_date) {
|
|
$dn_date = mktime (0, 0, 0, $dt_date["m"], $dt_date["d"], $dt_date["Y"]);
|
|
if (!$dn_date)
|
|
$this->message ('error', $dt_date["Y"]."-".$dt_date["d"]."-".$dt_date["m"]." : ".$this->plugin->getLang ('mktimeError').'<br/>'.NL);
|
|
return $dn_date;
|
|
}
|
|
/* Check date format 31/12/2000 */
|
|
function checkDS ($ds_date) {
|
|
return
|
|
preg_match ("#([0-9]{8})#", $ds_date, $dumy);
|
|
}
|
|
/* Change date format from MM/DD/AAAA to number */
|
|
function df2ds ($df_date) {
|
|
$df_date = trim ($df_date);
|
|
if (!$df_date)
|
|
return;
|
|
if ("!" == $df_date)
|
|
$ds_date = date ("Ymd");
|
|
elseif (preg_match ("#\+(?<delta>[0-9]+)#", $df_date, $matches))
|
|
$ds_date = sprintf ("%08d", date ("Ymd", mktime (0, 0, 0, date ("n"), date ("j")+$matches["delta"], date ("Y"))));
|
|
elseif (preg_match ("#\-(?<delta>[0-9]+)#", $df_date, $matches))
|
|
$ds_date = sprintf ("%08d", date ("Ymd", mktime (0, 0, 0, date ("n"), date ("j")-$matches["delta"], date ("Y"))));
|
|
elseif (preg_match ("#".$this->currentDateFormat ["longScan"]."#", $df_date, $dt_date))
|
|
$ds_date = sprintf ("%04d%02d%02d", $dt_date["Y"], $dt_date["m"], $dt_date["d"]);
|
|
elseif (preg_match ("#".$this->currentDateFormat ["shortScan"]."#", $df_date, $dt_date))
|
|
$ds_date = sprintf ("20%02d%02d%02d", $dt_date["Y"], $dt_date["m"], $dt_date["d"]);
|
|
else
|
|
$ds_date = "{$df_date}";
|
|
return $ds_date;
|
|
}
|
|
/* Change date format from number to MM/DD/AAAA */
|
|
function ds2df ($ds_date) {
|
|
$ds_date = trim ($ds_date);
|
|
if (preg_match ("#(?<Y>[0-9][0-9][0-9][0-9])(?<m>[0-9][0-9])(?<d>[0-9][0-9])#", $ds_date, $dt_date))
|
|
return sprintf ("%02d/%02d/%04d",
|
|
$dt_date[$this->currentDateFormat["fieldName"][0]],
|
|
$dt_date[$this->currentDateFormat["fieldName"][1]],
|
|
$dt_date[$this->currentDateFormat["fieldName"][2]]);
|
|
else
|
|
return "{$ds_date}";
|
|
}
|
|
function ds2ln ($ds_date, $bold = false) {
|
|
$ds_date = trim ($ds_date);
|
|
if (preg_match ("#(?<Y>[0-9][0-9][0-9][0-9])(?<m>[0-9][0-9])(?<d>[0-9][0-9])#", $ds_date, $dt_date)) {
|
|
// XXX prévoir le format anglais
|
|
setlocale (LC_TIME, 'fr_FR.utf8','fra');
|
|
return strftime (($bold ? "**%A %e %B** %Y" : "%A %e %B %Y"),
|
|
mktime (0, 0, 0,
|
|
$dt_date[$this->currentDateFormat["fieldName"][1]],
|
|
$dt_date[$this->currentDateFormat["fieldName"][0]],
|
|
$dt_date[$this->currentDateFormat["fieldName"][2]]));
|
|
} else
|
|
return "{$ds_date}";
|
|
}
|
|
|
|
/* Convert array on string (words seperated bay '|') */
|
|
static function array2string ($array) {
|
|
if (!$array)
|
|
return "";
|
|
$array = array_unique ($array);
|
|
if (in_array ("", $array))
|
|
$array = array_diff ("", $array);
|
|
if (count ($array) < 1)
|
|
return "";
|
|
return implode ("|", $array);
|
|
}
|
|
/* Convert array on string (words seperated bay '|') */
|
|
function assocImplode ($array, $vSep = '|', $kSep = ':') {
|
|
$result = "";
|
|
foreach ($array as $k => $v) {
|
|
$result .= $vSepNeeded.$k.$kSep.$v;
|
|
$vSepNeeded = $vSep;
|
|
}
|
|
return $result;
|
|
}
|
|
/* Convert array on string (words seperated bay '|') */
|
|
function assocExplode ($string, $vSep = '|', $kSep = ':') {
|
|
$result = array ();
|
|
foreach (explode ($vSep, $string) as $kv) {
|
|
$data = explode ($kSep, $kv);
|
|
$result [$data[0]] = $data[1];
|
|
}
|
|
return $result;
|
|
}
|
|
/* Convert array on string (words seperated bay '|') */
|
|
// $ find data/[mp]*/membres/*/agenda/*/* data/[mp]*/commun/agenda/*/* -type f -print > dumy
|
|
// $ emacs dumy
|
|
// C-x ( mv ' ' C-k C-y ' ' C-y C-f C-x )
|
|
// M-1000 C-x e
|
|
// C-M-%
|
|
// ^\([^ ]* [^ ]* [^ ]*agenda/[^/ ]*_\)/ => \1
|
|
// C-M-%
|
|
// ^\([^ ]* [^ ]* [^ ]*agenda/[^/ ]*_\)/ => \1
|
|
// C-M-%
|
|
// ^\([^ ]* [^ ]* [^ ]*agenda/[^/ ]*\)/ => \1_
|
|
// $ find data/[mp]*/membres/*/agenda/* -type d -exec rmdir {} \; -print
|
|
function removeSep ($titleId) {
|
|
return strtr ($titleId, ':/;', ' ');
|
|
}
|
|
|
|
function getPageId ($schedule) {
|
|
return ":".
|
|
$this->scheduleDir.":".
|
|
($schedule->shared ? $this->sharedDir : $schedule->member).":".
|
|
$this->removeSep ($schedule->title);
|
|
}
|
|
|
|
function resetOddEven () {
|
|
$this->oddEven = 0;
|
|
}
|
|
function switchOddEven () {
|
|
$this->oddEven = 1 - $this->oddEven;
|
|
}
|
|
|
|
function getOddEven () {
|
|
return $this->oddEvenValues [$this->oddEven];
|
|
}
|
|
|
|
static function createDirIsNeeded ($dir) {
|
|
if (is_dir ($dir))
|
|
return;
|
|
@mkdir ($dir);
|
|
@chmod ($dir, 0775);
|
|
}
|
|
|
|
// ============================================================
|
|
function __construct ($plugin) {
|
|
$this->plugin = $plugin;
|
|
$this->scheduleSaveAttributsName = array_merge ($this->scheduleRequestAttributsName, array ("weekDays"));
|
|
global $conf;
|
|
$savedir = ((!$conf['savedir'] || strpos ($conf['savedir'], '.') === 0) ? DOKU_INC : "").$conf['savedir']."/";
|
|
$this->cacheRootDir = $savedir."cache/schedule/";
|
|
$this->dataRootDir = $savedir.trim ($this->plugin->getConf ('dataDir').'/');
|
|
scheduleRoot::createDirIsNeeded ($this->cacheRootDir);
|
|
scheduleRoot::createDirIsNeeded ($this->dataRootDir);
|
|
$this->scheduleGroup = trim ($this->plugin->getConf ('scheduleGroup'));
|
|
$this->groupsDir = trim ($this->plugin->getConf ('groupsDir'));
|
|
$this->scheduleDir = trim ($this->plugin->getConf ('scheduleDir'));
|
|
$this->sharedDir = trim ($this->plugin->getConf ('sharedDir'));
|
|
|
|
foreach (explode ('|', $this->plugin->getConf ('scheduleWhat')) as $tmpCatDef) {
|
|
$tmpCatExp = explode (':', trim ($tmpCatDef));
|
|
$tmpCat = trim ($tmpCatExp[0]);
|
|
foreach (explode (',', $tmpCatExp[1]) as $tmpWhat) {
|
|
$tmpWhat = trim ($tmpWhat);
|
|
$this->scheduleWhat[$tmpWhat] = $tmpCat;
|
|
}
|
|
}
|
|
$this->scheduleAudience [""] = $this->plugin->getLang ('audienceChoice');
|
|
foreach (explode (',', $this->plugin->getConf ('scheduleAudience')) as $tmpAudience)
|
|
$this->scheduleAudience[trim ($tmpAudience)] = trim ($tmpAudience);
|
|
$this->iconName = $this->plugin->getConf ('iconName');
|
|
$this->iconWidth = $this->plugin->getConf ('iconWidth');
|
|
foreach (array (false, true) as $sharedVal) {
|
|
$tmp = $this->plugin->getLang ('shared');
|
|
$this->scheduleShared[] = trim ($tmp[$sharedVal]);
|
|
}
|
|
$this->currentDateFormat = $this->dateFormat [$this->plugin->getLang ('dateFormat')];
|
|
|
|
global $INFO;
|
|
$this->isAdmin =
|
|
isset ($INFO ['userinfo']) &&
|
|
isset ($INFO ['userinfo']['grps']) &&
|
|
in_array (trim ($this->plugin->getConf ('adminGroup')), $INFO ['userinfo']['grps']);
|
|
}
|
|
|
|
// ============================================================
|
|
// Manage XML file
|
|
// ============================================================
|
|
/* read lodging config */
|
|
function readConfig ($dir) {
|
|
$oldFileName = $dir.$this->oldConfigFile;
|
|
$fileName = $dir.$this->configFile;
|
|
|
|
// rename old fashion membre file name
|
|
if (file_exists ($oldFileName)) {
|
|
// XXX migration
|
|
rename ($oldFileName, $fileName);
|
|
$exclude = ".|..|".$this->scheduleRoot->configFile;
|
|
$exclude_array = explode("|", $exclude);
|
|
$pathDir = rtrim ($dir, "/") . "/";
|
|
if (is_dir($pathDir)) {
|
|
$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 ('#.*\.xml$#i', $file, $b))
|
|
rename ($pathFile, $pathDir.$this->mbrPrefix.$file);
|
|
}
|
|
}
|
|
}
|
|
if (!file_exists ($fileName))
|
|
return false;
|
|
$result = array ();
|
|
// if (! class_exists ('DOMDocument'))
|
|
// return $result;
|
|
$xml = new DOMDocument ("1.0", "utf8");
|
|
$xml->load ($fileName);
|
|
$root = $xml->documentElement;
|
|
foreach ($this->configAttributsName as $field) {
|
|
$element = $root->getElementsByTagName ($field);
|
|
if ($element)
|
|
$result [$field] = $element->item (0)->nodeValue;
|
|
}
|
|
return $result;
|
|
}
|
|
/* write lodging config */
|
|
function writeConfig ($schedules) {
|
|
$fileName = $schedules->dataDir.$this->configFile;
|
|
scheduleRoot::createDirIsNeeded ($schedules->dataDir);
|
|
// if (! class_exists ('DOMDocument'))
|
|
// return;
|
|
$xml = new DOMDocument ("1.0", "utf8");
|
|
$root = $xml->createElement ("schedule");
|
|
$xml->appendChild ($root);
|
|
foreach ($this->configAttributsName as $field)
|
|
$root->appendChild ($xml->createElement ($field, htmlspecialchars ($schedules->$field)));
|
|
$xml->formatOutput = true;
|
|
$xml->save ($fileName);
|
|
chmod ($fileName, 0664);
|
|
}
|
|
|
|
// ============================================================
|
|
function manageAction ($request) {
|
|
if (!$this->isAdmin)
|
|
return;
|
|
$md5 = $request['md5'];
|
|
if (!$md5)
|
|
return;
|
|
$schedules = new schedules ($this, $request[$md5]['ns']);
|
|
switch ($request["action"]) {
|
|
|
|
case 'moveSchedules':
|
|
$md5 = $request['md5'];
|
|
$date = $this->df2ds ($request[$md5]['date']);
|
|
$md5bis = $request[$md5]['toNs'];
|
|
if (!$date)
|
|
return;
|
|
$src = new schedules ($this, $request[$md5]['ns']);
|
|
$src->load ();
|
|
$dst = new schedules ($this, $request[$md5bis]['ns']);
|
|
$dst->load ();
|
|
$filter = array ();
|
|
foreach ($src->allSchedules as $id => $schedule)
|
|
if (($schedule->to ? $schedule->to : $schedule->from) < $date)
|
|
$filter [$id] = $schedule;
|
|
foreach ($filter as $id => $schedule) {
|
|
$dst->addSchedule ($schedule);
|
|
$src->removeSchedule ($id);
|
|
}
|
|
$dst->writeSchedules ();
|
|
$src->writeSchedules ();
|
|
|
|
unset ($_REQUEST['schd']);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
// ============================================================
|
|
function printForm () {
|
|
if (!$this->isAdmin)
|
|
return;
|
|
$list = $this->readAllSchedules ();
|
|
echo
|
|
'<form method="POST" action="" onSubmit="return false;" >'.NL.
|
|
' <table class="admin" >'.NL.
|
|
' <thead>'.NL.
|
|
// XXX getLang ()
|
|
' <tr><th>Description</th><th>Valeurs</th></tr>'.NL.
|
|
' </thead>'.NL.
|
|
' <tbody>'.NL;
|
|
$this->resetOddEven ();
|
|
foreach ($list as $md5 => $item) {
|
|
$nameSpace = $item ["nameSpace"];
|
|
$schedules = $item ["schedules"];
|
|
echo
|
|
' <tr class="'.$this->getOddEven ().'">'.NL.
|
|
' <td class="name">NameSpace</td>'.NL.
|
|
' <td class="value"><input type="hidden" name="schd['.$md5.'][ns]" value="'.$nameSpace.'"/>'.$nameSpace.'</td>'.NL.
|
|
' </tr>'.NL.
|
|
' <tr class="'.$this->getOddEven ().'">'.NL.
|
|
' <td class="name">MD5</td>'.NL.
|
|
' <td class="value">'.$md5.'</td>'.NL.
|
|
' </tr>'.NL.
|
|
' <tr class="'.$this->getOddEven ().'">'.NL.
|
|
' <td class="name">Members</td>'.NL.
|
|
' <td class="value">'.count ($schedules->memberSchedules).'</td>'.NL.
|
|
' </tr>'.NL.
|
|
' <tr class="'.$this->getOddEven ().'">'.NL.
|
|
' <td class="name">Events</td>'.NL.
|
|
' <td class="value">'.count ($schedules->datedSchedules).'</td>'.NL.
|
|
' </tr>'.NL.
|
|
' <tr class="'.$this->getOddEven ().'">'.NL.
|
|
' <td class="name">Repeated</td>'.NL.
|
|
' <td class="value">'.count ($schedules->repeatedSchedules).'</td>'.NL.
|
|
' </tr>'.NL.
|
|
' <tr class="'.$this->getOddEven ().'">'.NL.
|
|
' <td class="name">Date</td>'.NL.
|
|
' <td><input type="text" name="schd['.$md5.'][date]" value="'.'" placeholder="'.$this->plugin->getLang ('rootMoveDatePH').'"/></td>'.NL.
|
|
' </tr>'.NL.
|
|
' <tr class="'.$this->getOddEven ().'">'.NL.
|
|
' <td class="name">Vers</td>'.NL.
|
|
' <td><select name="schd['.$md5.'][toNs]"/>'.NL;
|
|
foreach ($list as $md5bis => $itemBis)
|
|
if ($md5bis != $md5)
|
|
echo
|
|
' <option value="'.$md5bis.'">'.$itemBis["nameSpace"].'</option>'.NL;
|
|
echo
|
|
' </select></td>'.NL.
|
|
' </tr>'.NL.
|
|
' <tr class="'.$this->getOddEven ().'">'.NL.
|
|
' <td class="name">Action</td>'.NL.
|
|
' <td><input type="submit" name="action" value="moveSchedules" onClick="scheduleAjax(this.form,\'moveSchedules\',\''.$md5.'\')" /></td>'.NL.
|
|
' </tr>'.NL;
|
|
$this->switchOddEven ();
|
|
}
|
|
echo
|
|
' </tbody>'.NL.
|
|
' </table>'.NL.
|
|
'</form>'.NL;
|
|
}
|
|
|
|
// ============================================================
|
|
function readAllSchedules () {
|
|
$exclude_array = explode ("|", ".|..");
|
|
if (!is_dir($this->dataRootDir))
|
|
return;
|
|
$pathDirObj = opendir ($this->dataRootDir);
|
|
while (false !== ($file = readdir ($pathDirObj))) {
|
|
$subDir = $this->dataRootDir.$file.'/';
|
|
if (in_array (strtolower ($file), $exclude_array) || !is_dir ($subDir))
|
|
continue;
|
|
$list [$file] = $this->readConfig ($subDir);
|
|
$list [$file]["schedules"] = new schedules ($this, $list [$file]["nameSpace"]);
|
|
$list [$file]["schedules"]->load ();
|
|
}
|
|
uasort ($list, "cmpScheduleConfig");
|
|
return $list;
|
|
}
|
|
|
|
function clearCache () {
|
|
$list = $this->readAllSchedules ();
|
|
foreach ($list as $md5 => $item) {
|
|
$schedules = $item ["schedules"];
|
|
$schedules->clearCache ();
|
|
}
|
|
}
|
|
|
|
// ============================================================
|
|
}
|