*
* Plugin Glossary: manage forms for glossary
*/
if(!defined('DOKU_INC'))
define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
if(!defined('DOKU_PLUGIN'))
define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
/* Sort glossary by definition */
function cmpGlossary ($a, $b) {
if ($a['word'] == $b['word'])
return 0;
return ($a['word'] < $b['word']) ? -1 : 1;
}
class glossary {
// ============================================================
// Config attributs
// ============================================================
var $cacheRootDir; // root cache directory
var $cacheDir; // cache directory for specific namespace
var $dataRootDir; // root data directory
var $dataDir; // data directory for specific namespace for xml file
var $recentDays; // time during the clock is display to indicate a nex definition
var $maxIP; // max proposition per guest user
var $propGroup; // user group without limits of proposition
var $adminGroup; // admin group who validate proposition
var $transSep; // line separator for translate if not empty
// ============================================================
// Constant attributs
// ============================================================
var $configFile = "config.xml"; // file config name
var $prop = "prop-"; // prefix for proposal
var $def = "def-"; // prefix for definition // XXXX
var $poll = "poll-"; // prefix for polling (evaluation per definition)
var $form = "form-"; // subset used in form
var $hide = "hide-"; // subset not used in form
var $statusFields = // fields managed per step (status)
array ("prop-" => array ("date", "ip", "email", "ns", "ticket", "word", "translate", "why"),
"def-" => array ("date", "ip", "email", "ns", "ticket", "useTicket", "word", "translate"),
"poll-" => array ("word", "view", "up", "down"),
"form-" => array ("ticket", "useTicket", "word", "translate", "why"),
"hide-" => array ("date", "ip", "email", "ns"));
var $oddEven = // for row color
array ("odd", "even");
var $imgDir;
// ============================================================
// Transcient attributs
// ============================================================
var $message = array (); // "notify" =>, "info" =>, "success" =>, "error" =>
var $plugin; // link to wiki plugin information (conf, lang, ...)
var $NS; // 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 $md5id; // the wiki id
var $sampleFile; // cache for sample
var $listFile; // cache for sample
// ============================================================
function createDirIsNeeded ($dir) {
if (is_dir ($dir))
return;
@mkdir ($dir);
@chmod ($dir, 0775);
}
function __construct ($plugin, $ns) {
$this->plugin = $plugin;
$this->imgDir = DOKU_REL.'lib/plugins/glossary/images/';
global $conf;
$savedir = ((!$conf['savedir'] || strpos ($conf['savedir'], '.') === 0) ? DOKU_INC : "").$conf['savedir']."/";
$this->cacheRootDir = $savedir."cache/glossary/";
$this->dataRootDir = $savedir.trim ($this->plugin->getConf ('dataDir').'/');
glossary::createDirIsNeeded ($this->cacheRootDir);
glossary::createDirIsNeeded ($this->dataRootDir);
$this->NS = cleanId (trim ($ns));
$this->md5ns = md5 ($this->NS);
$this->cacheDir = $this->cacheRootDir.$this->md5ns."/";
glossary::createDirIsNeeded ($this->cacheDir);
$this->dataDir = $this->dataRootDir.$this->md5ns."/";
glossary::createDirIsNeeded ($this->dataDir);
$this->sampleFile = $this->cacheDir."sample.cache";
$this->listFile = $this->cacheDir."list.cache";
$this->recentDays = $this->getConf ('recentDays');
$this->maxIP = $this->getConf ('maxIP');
$this->adminGroup = trim ($this->getConf ('adminGroup'));
$this->propGroup = trim ($this->getConf ('propGroup'));
$this->transSep = trim ($this->getConf ('transSep'));
}
function getConf ($name) {
return $this->plugin->getConf ($name);
}
function getLang ($name) {
return $this->plugin->getLang ($name);
}
// function isAdmin ($name) {
// return $this->plugin->isAdmin ($name);
// }
function localFN ($name) {
return $this->plugin->localFN ($name);
}
/* messages container to be display before plugin */
function message ($type, $text) {
if (isset ($this->message[$type]))
$this->message[$type] .= ' ';
$this->message[$type] .= $text;
}
/* debug messages for admin only */
function debug ($text) {
global $INFO;
if (in_array ('admin', $INFO ['userinfo'] ['grps']))
$this->message ('notify', '
'.$text.'
');
}
/* get next parity for row color */
function nextOddEven (&$even) {
$result = $this->oddEven [$even];
$even = 1 - $even;
return $result;
}
// ============================================================
// Control rights
// ============================================================
/* true if the user has the admin rights */
function testAdminGroup () {
global $INFO;
return
isset ($INFO ['userinfo']['grps']) &&
in_array ($this->adminGroup, $INFO ['userinfo']['grps']);
}
/* true if the user has no proposition limits */
function testPropGroup () {
global $INFO;
return
isset ($INFO ['userinfo']['grps']) &&
in_array ($this->propGroup, $INFO ['userinfo']['grps']);
}
/* true if limit occured (i.e. problems => can't continued)*/
function maxIP (&$request) {
$ip = $request['ip'];
$count = 1;
$all = $this->readAllGlossary ($this->prop);
if (isset ($all[$this->md5id])) {
$this->message ('success', $this->getLang ('update'));
return false;
}
if ($this->testPropGroup ())
return false;
foreach ($all as $record)
if ($record['ip'] == $ip)
$count++;
if ($count <= $this->maxIP) {
if ($count == $this->maxIP)
$this->message ('notify', $this->getLang ('lastIP'));
return false;
}
$this->message ('error', $this->getLang ('maxIP'));
return true;
}
// ============================================================
// Control fields
// ============================================================
function testNotEmpty () {
return
$this->wordOk () || $this->translateOk () || $this->translateOk () || $this->ticketOk ();
}
function wordOk () {
return isset ($_REQUEST ['glossary']['word']) && trim ($_REQUEST ['glossary']['word']) != "";
}
function translateOk () {
return isset ($_REQUEST ['glossary']['translate']) && trim ($_REQUEST ['glossary']['translate']) != "";
}
function ticketOk () {
return isset ($_REQUEST ['glossary']['ticket']) && trim ($_REQUEST ['glossary']['ticket']) != "";
}
// ============================================================
// Manage XML file
// ============================================================
/* read lodging config */
function readConfig ($dir) {
$fileName = $dir.$this->configFile;
if (!file_exists ($fileName))
return false;
$xml = new DOMDocument ("1.0", "utf8");
$xml->load ($fileName);
$root = $xml->documentElement;
$this->lastNotification = $root->getElementsByTagName ("lastNotification")->item (0)->nodeValue;
$this->lastNotificationReset = $root->getElementsByTagName ("lastNotificationReset")->item (0)->nodeValue;
return $root->getElementsByTagName ("nameSpace")->item (0)->nodeValue;
}
/* write lodging config */
function writeConfig () {
if ($this->NS == false)
return;
$fileName = $this->dataDir.$this->configFile;
@mkdir ($this->dataDir);
@chmod ($this->dataDir, 0775);
$xml = new DOMDocument ("1.0", "utf8");
$root = $xml->createElement ("glossary");
$xml->appendChild ($root);
$root->appendChild ($xml->createElement ("nameSpace", htmlspecialchars ($this->NS)));
$root->appendChild ($xml->createElement ("lastNotification", htmlspecialchars ($this->lastNotification)));
$root->appendChild ($xml->createElement ("lastNotificationReset", htmlspecialchars ($this->lastNotificationReset)));
$xml->formatOutput = true;
$xml->save ($fileName);
chmod ($fileName, 0664);
}
/* read all propositions, definitions, polls */
function readAllGlossary ($status) {
if (!is_dir ($this->dataDir))
return;
if ($this->NS == false)
return;
$result = array ();
$exclude_array = explode ("|", ".|..|".$this->configFile);
$pathDirObj = opendir ($this->dataDir);
while (false !== ($file = readdir ($pathDirObj))) {
if (in_array (strtolower ($file), $exclude_array) || !preg_match ('#'.$status.'(.*)\.xml$#i', $file, $regs))
continue;
$result[$regs[1]] = $this->readGlossary ($regs[1], $status, LOCK_SH);
}
uasort ($result, "cmpGlossary");
return $result;
}
/* read one proposition, definition, poll */
function readGlossary ($md5id, $status, $lock) {
$fileName = $this->dataDir.$status.$md5id.".xml";
if (!file_exists ($fileName))
return false;
$lock = LOCK_SH;
if ($lock != LOCK_SH) {
$fp = fopen ($fileName, "r+");
if (!flock ($fp, $lock)) {
$this->message ("error", "can't lock file ".$fileName.".");
return;
}
}
$xml = new DOMDocument ("1.0", "utf8");
$xml->load ($fileName);
$root = $xml->documentElement;
$result = array ();
foreach ($this->statusFields [$status] as $field)
$result [$field] = $root->getElementsByTagName ($field)->item (0)->nodeValue;
return $result;
}
/* write one proposition, definition, poll */
function writeGlossary ($md5id, &$values, $status) {
if (! isset ($values['ns']) || $values['ns'] == "")
$values['ns'] = $this->NS; // XXX compatibilité
$xml = new DOMDocument ("1.0", "utf8");
$root = $xml->createElement ("glossary");
$xml->appendChild ($root);
foreach ($this->statusFields [$status] as $field)
$root->appendChild ($xml->createElement ($field, htmlspecialchars ($values [$field])));
$xml->formatOutput = true;
$fileName = $this->dataDir.$status.$md5id.".xml";
$xml->save ($fileName);
chmod ($fileName, 0664);
//flock (fopen ($fileName, "r+"), LOCK_UN);
}
/* remove one proposition, definition, poll */
function removeGlossary ($md5id, $status) {
$fileName = $this->dataDir.$status.$md5id.".xml";
@unlink ($fileName);
}
/* count file propositions, definitions, polls */
function getGlosarySize ($status, $md5ns) {
$subDir = $this->dataRootDir.$md5ns."/";
if (!is_dir ($subDir))
return 0;
$result = 0;
$exclude_array = explode ("|", ".|..|".$this->configFile);
$pathDirObj = opendir ($subDir);
while (false !== ($file = readdir ($pathDirObj))) {
if (in_array (strtolower ($file), $exclude_array) || !eregi ($status.'(.*)\.xml$', $file, $regs))
continue;
$result++;
}
return $result;
}
// ============================================================
// Actions to performed
// ============================================================
/* update proposition, definition */
function updateRequest (&$request, $status) {
$reread = false;
$update = false;
$this->md5id = md5 (trim ($request['ticket']));
$oldValues = $this->readGlossary ($this->md5id, $status, LOCK_SH);
if ($oldValues) {
foreach ($this->statusFields [$this->form] as $field) {
if ((!isset ($request[$field]) || $request[$field] == "") &&
$request[$field] != $oldValues [$field]) {
$request[$field] = $oldValues [$field];
$reread = true;
} elseif (isset ($request[$field]) && $request[$field] != "" &&
$request[$field] != $oldValues [$field]) {
$update = true;
}
}
foreach ($this->statusFields [$this->hide] as $field)
$request[$field] = $oldValues [$field];
if ($reread)
$this->message ('success', $this->getLang ('readData'));
return $update;
}
return true;
}
/* display poll */
function printPoll ($arg) {
echo
'