First
@ -1,2 +1,6 @@
|
||||
# glossary
|
||||
|
||||
DokuWiki Extensions : https://www.dokuwiki.org/plugin:glossary
|
||||
|
||||
In this case, French “Newspeak” expression are translate in the real world.
|
||||
|
||||
|
56
ajax.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* @license http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html
|
||||
* @author Francois Merciol <dokuplugin@merciol.fr>
|
||||
*
|
||||
* Plugin Glossary
|
||||
*/
|
||||
if (!defined ('DOKU_INC'))
|
||||
define ('DOKU_INC', realpath (dirname (__FILE__).'/../../../').'/');
|
||||
require_once (DOKU_INC.'inc/init.php');
|
||||
require_once (DOKU_INC.'inc/common.php');
|
||||
require_once (DOKU_INC.'inc/auth.php');
|
||||
if (isset ($_SERVER['REMOTE_USER']))
|
||||
$INFO['userinfo'] = $auth->getUserData ($auth->cleanUser ($_SERVER['REMOTE_USER']));
|
||||
{
|
||||
$glossaryPlugin =& plugin_load ('syntax', 'glossary_div');
|
||||
$glossary = new glossary ($glossaryPlugin, $_REQUEST ['glossary']['ns']);
|
||||
|
||||
$cacheCmd = true;
|
||||
switch ($_REQUEST ['glossary']['action']) {
|
||||
case 'clear':
|
||||
$glossary->clearCache (md5 ($_REQUEST ['glossary']['ns']));
|
||||
break;
|
||||
case 'clearAll':
|
||||
$glossary->clearCache (null);
|
||||
break;
|
||||
default:
|
||||
$cacheCmd = false;
|
||||
}
|
||||
if (!$cacheCmd) {
|
||||
ob_start ();
|
||||
switch ($_REQUEST ['glossary']['operation']) {
|
||||
case 'poll':
|
||||
$glossary->poll ();
|
||||
break;
|
||||
case 'record':
|
||||
$glossary->printProposal ();
|
||||
break;
|
||||
case $glossary->prop.'remove':
|
||||
$glossary->adminProposal ();
|
||||
break;
|
||||
case $glossary->def.'remove':
|
||||
case $glossary->def.'update':
|
||||
$glossary->adminDefinition ();
|
||||
case 'glos-remove':
|
||||
$glossary->adminGlossaries ();
|
||||
break;
|
||||
}
|
||||
$text = ob_get_contents ();
|
||||
ob_end_clean ();
|
||||
foreach ($glossary->message as $type => $msg)
|
||||
$text = '<div class="'.$type.'">'.$msg.'</div>'.$text;
|
||||
ptln ($text);
|
||||
}
|
||||
}
|
||||
?>
|
17
conf/default.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* @license http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html
|
||||
* @author Francois Merciol <dokuplugin@merciol.fr>
|
||||
*
|
||||
* Options for the Glossary Plugin
|
||||
*/
|
||||
$conf['dataDir'] = 'glossary';
|
||||
$conf['recentDays'] = 7;
|
||||
$conf['maxIP'] = 5;
|
||||
$conf['adminGroup'] = 'admin';
|
||||
$conf['propGroup'] = 'glossary';
|
||||
$conf['transSep'] = ';';
|
||||
$conf['propositionPage'] = '[[.:proposition|proposition]]';
|
||||
$conf['sampleDelai'] = 2*60*60;
|
||||
$conf['listDelai'] = 2*60*60;
|
||||
?>
|
18
conf/metadata.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* @license http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html
|
||||
* @author Francois Merciol <dokuplugin@merciol.fr>
|
||||
*
|
||||
* Metadata for configuration manager plugin
|
||||
* Additions for the Glossary plugin
|
||||
*/
|
||||
$meta['dataDir'] = array('string');
|
||||
$meta['recentDays'] = array('numeric');
|
||||
$meta['maxIP'] = array('numeric');
|
||||
$meta['adminGroup'] = array('string');
|
||||
$meta['propGroup'] = array('string');
|
||||
$meta['transSep'] = array('string');
|
||||
$meta['propositionPage'] = array('string');
|
||||
$meta['sampleDelai'] = array('numeric');
|
||||
$meta['listDelai'] = array('numeric');
|
||||
?>
|
938
glossary.class.php
Normal file
@ -0,0 +1,938 @@
|
||||
<?php
|
||||
/**
|
||||
* @license http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html
|
||||
* @author Francois Merciol <dokuplugin@merciol.fr>
|
||||
*
|
||||
* 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] .= '<br/>';
|
||||
$this->message[$type] .= $text;
|
||||
}
|
||||
/* debug messages for admin only */
|
||||
function debug ($text) {
|
||||
global $INFO;
|
||||
if (in_array ('admin', $INFO ['userinfo'] ['grps']))
|
||||
$this->message ('notify', '<pre>'.$text.'</pre>');
|
||||
}
|
||||
/* 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
|
||||
'<div class="glossary toolTip">'.NL;
|
||||
$this->printPollAjax (md5 (trim ($arg)));
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
function printPollAjax ($md5id) {
|
||||
$filename = $this->cacheDir."poll-".md5($md5id).".cache";
|
||||
if (file_exists ($filename)) {
|
||||
echo file_get_contents ($filename);
|
||||
return;
|
||||
}
|
||||
$poll = $this->readGlossary ($md5id, $this->poll, LOCK_SH);
|
||||
list ($scoreVal, $scoreImg) = $this->getScore ($poll);
|
||||
$text =
|
||||
'<a onClick="glossaryPoll(this,\''.$md5id.'\',\'down\',\''.$this->NS.'\');">'.NL.
|
||||
' <img src="'.$this->imgDir.'face-sad.png" /><span>'.$this->getLang ('tipPollDown').'</span>'.NL.
|
||||
'</a>'.
|
||||
$scoreImg.NL.
|
||||
'<a onClick="glossaryPoll(this,\''.$md5id.'\',\'up\',\''.$this->NS.'\');">'.NL.
|
||||
' <img src="'.$this->imgDir.'face-smile.png" /><span>'.$this->getLang ('tipPollUp').'</span>'.NL.
|
||||
'</a>';
|
||||
if (!$poll|| ($poll['up']+$poll['down'] < 1))
|
||||
$text .=
|
||||
'<br/><b>'.$this->getLang ('notPolledYet').'</b>';
|
||||
file_put_contents ($filename, $text);
|
||||
echo $text;
|
||||
}
|
||||
|
||||
function getScore ($poll) {
|
||||
$scoreImg = '<img src="'.$this->imgDir.'score';
|
||||
if ($poll && $poll["up"] + $poll["down"] > 0) {
|
||||
$scoreVal = (($poll["up"] - $poll["down"]) /
|
||||
(max (5, $poll["up"] + $poll["down"])));
|
||||
$scoreImg .= '-'.intval (round (($scoreVal+1)*3));
|
||||
} else
|
||||
$scoreVal = 0;
|
||||
$scoreImg .= '.png"/>';
|
||||
return array ($scoreVal, $scoreImg);
|
||||
}
|
||||
|
||||
/* update poll */
|
||||
function poll () {
|
||||
$request = &$_REQUEST ['glossary'];
|
||||
$md5id = $request['ticket'];
|
||||
$opinion = $request['opinion'];
|
||||
$all = $this->readAllGlossary ($this->def);
|
||||
if (! isset ($all[$md5id]) || !in_array ($opinion, $this->statusFields [$this->poll])) {
|
||||
$this->message ('error', $this->getLang ('noDef'));
|
||||
return;
|
||||
}
|
||||
$poll = $this->readGlossary ($md5id, $this->poll, LOCK_EX);
|
||||
if (!$poll)
|
||||
$poll = array ("word" => $all[$md5id]['word'], "up" => 0, "down" => 0);
|
||||
if ($poll [$opinion] != PHP_INT_MAX)
|
||||
$poll [$opinion]++;
|
||||
$this->writeGlossary ($md5id, $poll, $this->poll);
|
||||
$this->message ('success', $this->getLang ('writePoll'));
|
||||
@unlink ($this->cacheDir."poll-".md5($md5id).".cache");
|
||||
$this->printPollAjax ($md5id);
|
||||
}
|
||||
|
||||
|
||||
function incView ($md5id, $word) {
|
||||
$poll = $this->readGlossary ($md5id, $this->poll, LOCK_EX);
|
||||
if (!$poll)
|
||||
$poll = array ("word" => $word, "view" => 0, "up" => 0, "down" => 0);
|
||||
$poll ["view"]++;
|
||||
$this->writeGlossary ($md5id, $poll, $this->poll);
|
||||
return $poll;
|
||||
}
|
||||
|
||||
function clearCache ($nsMd5) {
|
||||
$exclude = ".|..";
|
||||
$exclude_array = explode("|", $exclude);
|
||||
$allNsMd5 = array ();
|
||||
if ($nsMd5)
|
||||
$allNsMd5[] = $nsMd5;
|
||||
else {
|
||||
$pathDirObj = opendir ($cacheRootDir);
|
||||
while (false !== ($file = readdir ($pathDirObj))) {
|
||||
if (in_array (strtolower ($file), $exclude_array))
|
||||
continue;
|
||||
$pathFile = $pathDir.$file;
|
||||
if (!is_dir ($pathFile))
|
||||
continue;
|
||||
$allNsMd5[] = $file;
|
||||
}
|
||||
}
|
||||
foreach ($allNsMd5 as $nsMd5) {
|
||||
$cacheDir = $this->cacheRootDir.$nsMd5."/";
|
||||
if (!is_dir ($cacheDir))
|
||||
break;
|
||||
$pathDirObj = opendir ($cacheDir);
|
||||
while (false !== ($file = readdir ($pathDirObj))) {
|
||||
if (in_array (strtolower ($file), $exclude_array))
|
||||
continue;
|
||||
$pathFile = $cacheDir.$file;
|
||||
if (!is_file ($pathFile))
|
||||
continue;
|
||||
if (eregi ('.*\.cache$', $file, $b))
|
||||
unlink ($pathFile);
|
||||
}
|
||||
@rmdir ($cacheDir);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function manageRecord (&$request, $status, $needCaptcha) {
|
||||
if (!$this->testNotEmpty ())
|
||||
return;
|
||||
|
||||
if ($this->ticketOk ()) {
|
||||
if (!$this->updateRequest ($request, $status))
|
||||
return;
|
||||
} else {
|
||||
$request ['ticket'] = substr (md5 (date ('YmdHis')), 0, 12);
|
||||
$this->md5id = md5 (trim ($request ['ticket']));
|
||||
}
|
||||
if ($needCaptcha && (!$captcha =& plugin_load ('helper', 'captcha') || !$captcha->check ())) {
|
||||
$this->message ('error', $this->getLang ('badCaptcha'));
|
||||
return;
|
||||
}
|
||||
if (!$this->wordOk ()) {
|
||||
$this->message ('error', $this->getLang ('wordMandatory'));
|
||||
return;
|
||||
}
|
||||
if (!$this->translateOk ()) {
|
||||
$this->message ('error', $this->getLang ('translateMandatory'));
|
||||
return;
|
||||
|
||||
}
|
||||
if (! isset ($request['date']) || $request['date'] == "") {
|
||||
$request['date'] = date ('YmdHis');
|
||||
$request['ip'] = $_SERVER ['REMOTE_ADDR'];
|
||||
global $INFO;
|
||||
if (isset ($INFO['userinfo']['mail']))
|
||||
$request['email'] = $INFO['userinfo']['mail'];
|
||||
$request['ns'] = $this->NS;
|
||||
}
|
||||
unset ($request['operation']);
|
||||
sleep (1);
|
||||
if ($status == $this->prop && $this->maxIP ($request))
|
||||
return;
|
||||
$this->writeGlossary ($this->md5id, $request, $status);
|
||||
$this->message ('success', $this->getLang ('proposalRecorded').'<b>'.$request['ticket']."</b>.");
|
||||
$this->adminNotification ($request, $status);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Result for display
|
||||
// ============================================================
|
||||
function getDefinitionSize () {
|
||||
return $this->getGlosarySize ($this->def, $this->md5ns);
|
||||
}
|
||||
function getProposalSize () {
|
||||
return $this->getGlosarySize ($this->prop, $this->md5ns);
|
||||
}
|
||||
function getPollSize () {
|
||||
return $this->getGlosarySize ($this->poll, $this->md5ns);
|
||||
}
|
||||
function printProposal () {
|
||||
global $INFO;
|
||||
$needCaptcha = !(isset ($INFO ['userinfo']) &&
|
||||
isset ($INFO ['userinfo']['grps']) &&
|
||||
$INFO ['userinfo']['grps']);
|
||||
$request = &$_REQUEST ['glossary'];
|
||||
if ($request['operation'] == "record")
|
||||
$this->manageRecord ($request, $this->prop, $needCaptcha);
|
||||
echo
|
||||
'<form method="post" action="" onsubmit="return glossaryAjax(this);">'.NL.
|
||||
' <table>'.NL.
|
||||
' <tr class="title">'.NL.
|
||||
' <th><img src="'.$this->imgDir.'stop.png" /> '.$this->getLang ('word').'</th>'.NL.
|
||||
' <th><img src="'.$this->imgDir.'one-way.png" /> '.$this->getLang ('translate').'</th>'.NL.
|
||||
' </tr><tr class="odd">'.NL.
|
||||
' <td>'.NL.
|
||||
' * <input type="text" name="glossary[word]" value="'.$request['word'].'" class="text" />'.NL.
|
||||
' </td><td>'.NL.
|
||||
' * <input type="text" name="glossary[translate]" value="'.$request['translate'].'" class="text" />'.NL.
|
||||
' </td>'.NL.
|
||||
' <tr class="title">'.NL.
|
||||
' <th>'.$this->getLang ('why').'</th>'.NL.
|
||||
' <th>'.NL.
|
||||
' <input type="hidden" name="glossary[operation]" value="record">'.NL.
|
||||
' <input type="hidden" name="glossary[ns]" value="'.$this->NS.'">'.NL.
|
||||
' <input type="submit" name="glossary[action]" value="'.$this->getLang (empty ($request['ticket']) ? 'proposal' : 'update').'" />'.NL.
|
||||
' <input type="reset" onClick="glossaryReset(this);glossaryUpdateProposalLabel(this.form)" value="'.$this->getLang ('new').'" />'.NL.
|
||||
' </th>'.NL.
|
||||
' </tr><tr class="odd">'.NL.
|
||||
' <td colspan="2"><textarea name="glossary[why]" class="why" />'.$request['why'].'</textarea></td>'.NL.
|
||||
' </tr><tr class="even">'.NL.
|
||||
' <td class="right">'.NL.
|
||||
' '.$this->getLang ('ticketIfUpdate').NL.
|
||||
' </td><td>'.NL.
|
||||
' <input type="text" name="glossary[ticket]" value="'.$request['ticket'].'" class="text" onChange="glossaryUpdateProposalLabel(this.form)" onKeypress="glossaryUpdateProposalLabel(this.form)" />'.NL.
|
||||
' </td>'.NL.
|
||||
' </tr>'.NL;
|
||||
if ($needCaptcha && $captcha =& plugin_load ('helper', 'captcha'))
|
||||
echo '<tr><td colspan=2>'.$captcha->getHTML ().'</td></tr>'.NL;
|
||||
echo
|
||||
' </table>'.NL;
|
||||
'</form>';
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function printSample () {
|
||||
if (file_exists ($this->sampleFile) &&
|
||||
(time () - filemtime ($this->sampleFile) < $this->getConf ('sampleDelai'))) {
|
||||
echo file_get_contents ($this->sampleFile);
|
||||
return;
|
||||
}
|
||||
|
||||
$all = $this->readAllGlossary ($this->def);
|
||||
$keys = array_keys ($all);
|
||||
$rand = array_rand ($keys);
|
||||
$record = $all [$keys [$rand]];
|
||||
$imgDir = DOKU_REL.'lib/plugins/glossary/images/';
|
||||
foreach (explode ($this->transSep, $record['word']) as $word)
|
||||
foreach (explode ($this->transSep, $record['translate']) as $translate) {
|
||||
$word = trim ($word);
|
||||
$translate = trim ($translate);
|
||||
$pageId = trim ($record['useTicket']);
|
||||
if (!$pageId)
|
||||
$pageId = trim ($record['ticket']);
|
||||
resolve_pageid ($this->NS, $pageId, $exists);
|
||||
$cleanId = cleanId ($pageId);
|
||||
$link = '<a class="wikilink1" href="'.DOKU_REL.$cleanId.'">';
|
||||
$text =
|
||||
'<div>'.$this->getLang ('word').'<br/><img src="'.$imgDir.'stop.png" align="left"/> <span class="glossaryWord"> '.$link.$word.' </a></span></div>'.NL.
|
||||
'<div>'.$this->getLang ('translate').'<br/><img src="'.$imgDir.'one-way.png" align="left"/> <span class="glossaryTranslate"> '.$link.$translate.' </a></span></div>'.NL;
|
||||
file_put_contents ($this->sampleFile, $text);
|
||||
echo $text;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function clearListFile () {
|
||||
@unlink ($this->listFile);
|
||||
}
|
||||
|
||||
function printList () {
|
||||
if ($this->testAdminGroup ()) {
|
||||
echo '<div><form>';
|
||||
foreach (array ('clear', 'clearAll') as $action)
|
||||
echo '<input value="'.$this->getLang ($action).'" onclick="javascript:glossarySendClear (\''.$action.'\', \''.$this->NS.'\')" type="button">';
|
||||
echo '</form></div>';
|
||||
}
|
||||
if (file_exists ($this->listFile) &&
|
||||
(time () - filemtime ($this->listFile) < $this->getConf ('listDelai'))) {
|
||||
echo file_get_contents ($this->listFile);
|
||||
return;
|
||||
}
|
||||
|
||||
$all = $this->readAllGlossary ($this->def);
|
||||
$poll = $this->readAllGlossary ($this->poll);
|
||||
$text =
|
||||
'<table>'.NL.
|
||||
' <tr class="title">'.NL.
|
||||
' <th></th>'.NL.
|
||||
' <th class="toolTip">'.NL.
|
||||
' <a onClick="glossarySort(this,glossaryComparatorWord);"><span>'.$this->getLang ('tipWord').'</span><img src="'.$this->imgDir.'stop.png" /></a>'.NL.
|
||||
' <a onClick="glossarySort(this,glossaryComparatorTranslate);"><span>'.$this->getLang ('tipTranslate').'</span><img src="'.$this->imgDir.'one-way.png" /></a>'.NL.
|
||||
' <a onClick="glossarySort(this,glossaryComparatorDate);"><span>'.$this->getLang ('tipDate').'</span><img src="'.$this->imgDir.'clock.png" /></a>'.NL.
|
||||
' <a onClick="glossarySort(this,glossaryComparatorView);"><span>'.$this->getLang ('tipView').'</span><img src="'.$this->imgDir.'eye.png" /></a>'.NL.
|
||||
' <a onClick="glossarySort(this,glossaryComparatorScore);"><span>'.$this->getLang ('tipScore').'</span><img src="'.$this->imgDir.'score-all.png" width="32" /></a>'.NL.
|
||||
' </th>'.NL.
|
||||
' <th>'.$this->getLang ('why').'</th>'.NL.
|
||||
' <th><img src="'.$this->imgDir.'stop.png" /> '.$this->getLang ('word').'</th>'.NL.
|
||||
' <th colspan="2" class="toolTip" style="white-space: nowrap;">'.NL.
|
||||
' <form onsubmit="javascript:glossarySearch(this.elements[0]);return false;">'.NL.
|
||||
' <span>'.$this->getLang ('tipSearch').'</span><img src="'.$this->imgDir.'search.png" />'.NL.
|
||||
' <input type="text" name="glossary[search]" value="" class="search" keyup="glossarySearch(this);" onChange="glossarySearch(this);" />'.NL.
|
||||
' </form>'.NL.
|
||||
' </th>'.NL.
|
||||
' <th><img src="'.$this->imgDir.'one-way.png" /> '.$this->getLang ('translate').'</th>'.NL.
|
||||
' <th>'.$this->getLang ('poll').'</th>'.NL.
|
||||
' </tr>';
|
||||
$even = 0;
|
||||
$recentTime = mktime (0, 0, 0, date ("n"), date ("j")-$this->recentDays, date ("Y"));
|
||||
$recent = date ("YmdHis", $recentTime);
|
||||
global $ID;
|
||||
// XXX bug si empty ($this->transSep)
|
||||
$canInc = true;
|
||||
foreach ($all as $md5id => $record)
|
||||
foreach (explode ($this->transSep, $record['word']) as $word)
|
||||
foreach (explode ($this->transSep, $record['translate']) as $translate) {
|
||||
$word = trim ($word);
|
||||
$translate = trim ($translate);
|
||||
$pageId = trim ($record['useTicket']);
|
||||
if (!$pageId)
|
||||
$pageId = trim ($record['ticket']);
|
||||
resolve_pageid ($this->NS, $pageId, $exists);
|
||||
$style = false;
|
||||
$imgClock = '';
|
||||
if ($record['date'] > $recent) {
|
||||
$opacity = 1;
|
||||
if (preg_match ("#(?<Y>[0-9]{4})(?<m>[0-9]{1,2})(?<d>[0-9]{1,2})#", $record['date'], $dt_date)) {
|
||||
$delta = (mktime (0, 0, 0, $dt_date["m"], $dt_date["d"], $dt_date["Y"]) - $recentTime) / 86400;
|
||||
$opacity = ($delta)/($this->recentDays+1);
|
||||
}
|
||||
$imgClock = '<img src="'.$this->imgDir.'clock.png" style="opacity:'.$opacity.';" />';
|
||||
}
|
||||
$cleanId = cleanId ($pageId);
|
||||
if ($canInc && $ID == $cleanId) {
|
||||
$poll [$md5id] = $this->incView ($md5id, $word);
|
||||
$canInc = false;
|
||||
}
|
||||
$link = '<a href="'.DOKU_REL.$cleanId.'">';
|
||||
list ($scoreVal, $scoreImg) = $this->getScore ($poll [$md5id]);
|
||||
$text .=
|
||||
'<tr class="'.$this->nextOddEven ($even).'"'.NL.
|
||||
' word="'.$word.'" translate="'.$translate.'"'.NL.
|
||||
' date="'.$record['date'].'" view="'.$poll [$md5id]['view'].'" score="'.$scoreVal.'">'.NL.
|
||||
' <td class="count"></td>'.NL.
|
||||
' <td>'.$imgClock.'</td>'.NL.
|
||||
' <td class="why toolTip">'.$link.'<img src="'.$this->imgDir.'help.png"/><span>'.$this->getLang ('tipWhy').'</span></a></td>'.NL.
|
||||
' <td class="word" colspan="2">'.$link.$word.'</a></td>'.NL.
|
||||
' <td class="translate" colspan="2">'.$link.$translate.'</a></td>'.NL.
|
||||
' <td class="poll toolTip">'.$link.'<span>'.$this->getLang ('tipPoll').'</span>'.$scoreImg.'</a></td>'.NL.
|
||||
' </tr>';
|
||||
}
|
||||
$text .=
|
||||
NL.
|
||||
'</table>';
|
||||
file_put_contents ($this->listFile, $text);
|
||||
echo $text;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function manageUpdate (&$request) {
|
||||
if (!$this->testAdminGroup ())
|
||||
return;
|
||||
$this->manageRecord ($request, $this->def, false);
|
||||
}
|
||||
|
||||
function manageRemove (&$request) {
|
||||
if (!$this->testAdminGroup ())
|
||||
return;
|
||||
foreach (array ($this->prop, $this->def) as $status) {
|
||||
if (empty ($request[$status.'tickets']))
|
||||
continue;
|
||||
foreach ($request[$status.'tickets'] as $ticket) {
|
||||
$this->removeGlossary (md5 (trim ($ticket)), $status);
|
||||
$this->message ('info', $ticket." ".$this->getLang ('ticketDeleted'));
|
||||
if ($status == $this->def) {
|
||||
$pageId = $ticket;
|
||||
resolve_pageid ($this->NS, $pageId, $exists);
|
||||
if ($exists) {
|
||||
saveWikiText ($pageId, "", "wizard remove");
|
||||
$this->message ('info', $pageId." ".$this->getLang ('pageDeleted'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function printManagedList ($status) {
|
||||
$all = $this->readAllGlossary ($status);
|
||||
echo
|
||||
'<form method="post" action="" onsubmit="return glossaryAjax(this);">'.NL.
|
||||
' <table>'.NL.
|
||||
' <tr class="title">'.NL.
|
||||
' <th></th>'.NL;
|
||||
foreach (array_diff ($this->statusFields [$status], array ("ns")) as $field)
|
||||
echo
|
||||
' <th>'.$this->getLang ($field).'</th>'.NL;
|
||||
echo
|
||||
' </tr>';
|
||||
$even = 0;
|
||||
foreach ($all as $record) {
|
||||
echo
|
||||
'<tr class="'.$this->nextOddEven ($even).'">'.NL.
|
||||
' <td><input type="checkbox" name="glossary['.$status.'tickets][]" value="'.$record['ticket'].'"/></td>'.NL.
|
||||
' <td>'.substr ($record['date'],0, 8).'</td>'.NL.
|
||||
' <td>'.$record['ip'].'</td>'.NL.
|
||||
' <td>'.$record['email'].'</td>'.NL.
|
||||
' <td>'.$record['ticket'].'</td>'.NL;
|
||||
if ($status == $this->def)
|
||||
echo
|
||||
' <td>'.$record['useTicket'].'</td>'.NL;
|
||||
echo
|
||||
' <td>'.$record['word'].'</td>'.NL.
|
||||
' <td>'.$record['translate'].'</td>'.NL;
|
||||
if ($status == $this->prop)
|
||||
echo
|
||||
' <td>'.str_replace ("\n", "<br/>\n", $record['why']).'</td>'.NL;
|
||||
echo
|
||||
' </tr>';
|
||||
}
|
||||
echo
|
||||
'<tr>'.NL.
|
||||
' <td colspan="2">'.NL.
|
||||
' <input type="hidden" name="glossary[operation]" value="'.$status.'remove">'.NL.
|
||||
' <input type="hidden" name="glossary[ns]" value="'.$this->NS.'">'.NL.
|
||||
' <input type="submit" name="glossary[action]" value="'.$this->getLang ('remove').'"/></td>'.NL.
|
||||
' <td colspan="6"></td>'.NL.
|
||||
' </tr>'.NL.
|
||||
' </table>'.NL.
|
||||
' </form>'.NL;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function printManagedForm (&$request) {
|
||||
echo
|
||||
'<form method="post" action="" onsubmit="return glossaryAjax(this);">'.NL.
|
||||
' <table>'.NL.
|
||||
' <tr class="title">'.NL.
|
||||
' <th></th>'.NL.
|
||||
' <th><img src="'.$this->imgDir.'stop.png" /> '.$this->getLang ('word').'</th>'.NL.
|
||||
' <th><img src="'.$this->imgDir.'one-way.png" /> '.$this->getLang ('translate').'</th>'.NL.
|
||||
' </tr><tr class="'.$this->oddEven [0].'">'.NL.
|
||||
' <td><input type="reset" onClick="glossaryReset(this)" value="'.$this->getLang ('new').'" /></td>'.NL.
|
||||
' <td><input type="text" name="glossary[word]" value="'.$request['word'].'" class="text" /></td>'.NL.
|
||||
' <td><input type="text" name="glossary[translate]" value="'.$request['translate'].'" class="text" /></td>'.NL.
|
||||
' </tr><tr class="title">'.NL.
|
||||
' <th></th>'.NL.
|
||||
' <th>'.$this->getLang ('ticket').'</th>'.NL.
|
||||
' <th>'.$this->getLang ('useTicket').'</th>'.NL.
|
||||
' </tr><tr class="'.$this->oddEven [0].'">'.NL.
|
||||
' <td>'.NL.
|
||||
' <input type="hidden" name="glossary[operation]" value="'.$this->def.'update">'.NL.
|
||||
' <input type="hidden" name="glossary[ns]" value="'.$this->NS.'">'.NL.
|
||||
' <input type="submit" name="glossary[action]" value="'.$this->getLang ('update').'"/></td>'.NL.
|
||||
' <td><input type="text" name="glossary[ticket]" value="'.$request['ticket'].'" class="text" /></td>'.NL.
|
||||
' <td><input type="text" name="glossary[useTicket]" value="'.$request['useTicket'].'" class="text" /></td>'.NL.
|
||||
' </tr>'.NL.
|
||||
' </table>'.NL.
|
||||
'</form>'.NL;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function createPage (&$request) {
|
||||
if (!$this->ticketOk ())
|
||||
return;
|
||||
$pageId = trim ($request['useTicket']);
|
||||
if (!$pageId)
|
||||
$pageId = trim ($request['ticket']);
|
||||
$this->md5id = md5 ($pageId);
|
||||
$values = $this->readGlossary ($this->md5id, $this->def, LOCK_SH);
|
||||
if (!$values)
|
||||
return;
|
||||
resolve_pageid ($this->NS, $pageId, $exists);
|
||||
if ($exists)
|
||||
return;
|
||||
$pageTpl = io_readfile ($this->localFN ('pageTemplate'));
|
||||
$wordTpl = io_readfile ($this->localFN ('wordTemplate'));
|
||||
$translateTpl = io_readfile ($this->localFN ('translateTemplate'));
|
||||
$wordList = '';
|
||||
foreach (explode ($this->transSep, $values['word']) as $word)
|
||||
$wordList .= str_replace ("@@WORD@@", $word, $wordTpl);
|
||||
$translateList = '';
|
||||
foreach (explode ($this->transSep, $values['word']) as $word)
|
||||
$translateList .= str_replace ("@@TRANSLATE@@", $word, $translateTpl);
|
||||
$replace = array ('@@WORD@@' => $wordList,
|
||||
'@@TRANSLATE@@' => $translateList,
|
||||
'@@POL@@' => $values['ticket'],
|
||||
'@@PROPOSITIONPAGE@@' => $this->getConf ('propositionPage'));
|
||||
$content = str_replace (array_keys ($replace), array_values ($replace), $pageTpl);
|
||||
saveWikiText ($pageId, $content, "wizard creation");
|
||||
$this->message ('success', $this->getLang ('createPage'));
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function glossariesRemove (&$request) {
|
||||
if (!$this->testAdminGroup ())
|
||||
return;
|
||||
if (empty ($request['dir']))
|
||||
return;
|
||||
foreach ($request['dir'] as $md5ns) {
|
||||
$subDir = $this->dataRootDir.$md5ns.'/';
|
||||
$ns = $this->readConfig ($subDir);
|
||||
if ($this->getGlosarySize ($this->def, $md5ns)+$this->getGlosarySize ($this->prop, $md5ns) > 0)
|
||||
$this->message ('error', $this->getLang ('glossaryNotEmpty').$ns." (".$md5ns.").");
|
||||
else {
|
||||
if (!is_dir ($subDir))
|
||||
continue;
|
||||
$pathDirObj = opendir ($subDir);
|
||||
while (false !== ($file = readdir ($pathDirObj))) {
|
||||
if (!eregi ($this->poll.'(.*)\.xml$', $file, $regs))
|
||||
continue;
|
||||
@unlink ($subDir.$file);
|
||||
}
|
||||
@unlink ($subDir.$this->configFile);
|
||||
@rmdir ($subDir);
|
||||
$this->message ('success', $this->getLang ('glossaryRemoved').$ns." (".$md5ns.").");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function printGlossariesList () {
|
||||
if (!is_dir ($this->dataRootDir))
|
||||
return;
|
||||
$list = array ();
|
||||
$exclude_array = explode ("|", ".|..");
|
||||
$pathDirObj = opendir ($this->dataRootDir);
|
||||
while (false !== ($file = readdir ($pathDirObj))) {
|
||||
$subDir = $this->dataRootDir.$file.'/';
|
||||
if (in_array (strtolower ($file), $exclude_array) || !is_dir ($subDir))
|
||||
continue;
|
||||
$ns = $this->readConfig ($subDir);
|
||||
$list [$file] =
|
||||
array ($ns,
|
||||
$this->getGlosarySize ($this->def, $file),
|
||||
$this->getGlosarySize ($this->prop, $file),
|
||||
$this->getGlosarySize ($this->poll, $file));
|
||||
}
|
||||
$even = 0;
|
||||
echo
|
||||
'<form method="post" action="" onsubmit="return glossaryAjax(this);">'.NL.
|
||||
' <table>'.NL.
|
||||
' <tr class="title">'.NL.
|
||||
' <th></th><th>directory</th><th>nameSpace</th><th>definition</th><th>proposal</th><th>poll</th>'.NL.
|
||||
' </tr>';
|
||||
foreach ($list as $md5ns => $data) {
|
||||
list ($ns, $def, $prop, $poll) = $data;
|
||||
echo
|
||||
'<tr class="'.$this->nextOddEven ($even).'">'.NL.
|
||||
' <td><input type="checkbox" name="glossary[dir][]" value="'.$md5ns.'"/></td> '.NL.
|
||||
' <td>'.$md5ns.'</td>'.NL.
|
||||
' <td>'.$ns.'</td>'.NL.
|
||||
' <td>'.$def.'</td>'.NL.
|
||||
' <td>'.$prop.'</td>'.NL.
|
||||
' <td>'.$poll.'</td>'.NL.
|
||||
' </tr>';
|
||||
}
|
||||
echo
|
||||
'<tr class="'.$this->nextOddEven ($even).'">'.NL.
|
||||
' <td colspan="2">'.NL.
|
||||
' <input type="hidden" name="glossary[operation]" value="glos-remove">'.NL.
|
||||
' <input type="submit" name="glossary[action]" value="'.$this->getLang ('remove').'"/></td>'.NL.
|
||||
' <td colspan="4"></td>'.NL.
|
||||
' </tr>'.NL.
|
||||
' </table>'.NL.
|
||||
'</form>';
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function adminProposal () {
|
||||
if (!$this->testAdminGroup ())
|
||||
return;
|
||||
$request = &$_REQUEST ['glossary'];
|
||||
if ($request['operation'] == $this->prop."remove")
|
||||
$this->manageRemove ($request);
|
||||
$this->printManagedList ($this->prop);
|
||||
$this->resetAdminNotification ();
|
||||
}
|
||||
|
||||
function adminDefinition () {
|
||||
if (!$this->testAdminGroup ())
|
||||
return;
|
||||
$request = &$_REQUEST ['glossary'];
|
||||
if ($request['operation'] == $this->def."remove")
|
||||
$this->manageRemove ($request);
|
||||
if ($request['operation'] == $this->def."update") {
|
||||
$this->manageUpdate ($request);
|
||||
$this->createPage ($request);
|
||||
}
|
||||
$this->clearListFile ();
|
||||
$this->printManagedForm ($request);
|
||||
$this->printManagedList ($this->def);
|
||||
}
|
||||
|
||||
function adminGlossaries () {
|
||||
if (!$this->testAdminGroup ())
|
||||
return;
|
||||
$request = &$_REQUEST ['glossary'];
|
||||
if ($request['operation'] == "glos-remove")
|
||||
$this->glossariesRemove ($request);
|
||||
$this->printGlossariesList ();
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function resetAdminNotification () {
|
||||
$subDir = $this->dataRootDir.$this->md5ns.'/';
|
||||
$this->readConfig ($subDir);
|
||||
$this->lastNotificationReset = date ('YmdHis');
|
||||
$this->writeConfig ();
|
||||
}
|
||||
|
||||
function adminNotification ($request, $status) {
|
||||
$this->readConfig ($this->dataRootDir.$this->md5ns.'/');
|
||||
if ($this->lastNotification <= $this->lastNotificationReset) {
|
||||
$this->lastNotification = date ('YmdHis');
|
||||
|
||||
global $auth;
|
||||
$users = $auth->retrieveUsers ();
|
||||
foreach ($users as $user => $userinfo) {
|
||||
$mailSubject = $this->getLang ('notifySubject');
|
||||
$mailContent = $this->getLang ('notifyContent');
|
||||
$mailContent = str_replace ('@WORD@', $request['word'], $mailContent);
|
||||
$mailContent = str_replace ('@TRANSLATE@', $request['translate'], $mailContent);
|
||||
|
||||
if (in_array ($this->adminGroup, $userinfo ['grps'])) {
|
||||
$mailTo = $userinfo['mail'];
|
||||
mail_send ($mailTo, $mailSubject, $mailContent);
|
||||
// XXX $this->debug (print_r (array ($mailTo, $mailSubject, $mailContent), 1));
|
||||
}
|
||||
}
|
||||
|
||||
$this->writeConfig ();
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
}
|
BIN
images/clock.png
Normal file
After Width: | Height: | Size: 1004 B |
BIN
images/eye.png
Normal file
After Width: | Height: | Size: 666 B |
BIN
images/face-sad.png
Normal file
After Width: | Height: | Size: 802 B |
BIN
images/face-smile.png
Normal file
After Width: | Height: | Size: 806 B |
BIN
images/help.png
Normal file
After Width: | Height: | Size: 897 B |
BIN
images/new.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
images/one-way.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
images/score-0.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
images/score-1.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
images/score-2.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
images/score-3.png
Normal file
After Width: | Height: | Size: 772 B |
BIN
images/score-4.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
images/score-5.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
images/score-6.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
images/score-all.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
images/score.png
Normal file
After Width: | Height: | Size: 772 B |
BIN
images/score.xcf
Normal file
BIN
images/search.png
Normal file
After Width: | Height: | Size: 783 B |
BIN
images/stop.png
Normal file
After Width: | Height: | Size: 872 B |
67
lang/en/lang.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* @license http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html
|
||||
* @author Francois Merciol <dokuplugin@merciol.fr>
|
||||
*
|
||||
* English language file
|
||||
*/
|
||||
|
||||
// javascript
|
||||
$lang['js'] =
|
||||
array ('pleaseWait' => 'Connection to the server in progress ...',
|
||||
'proposal' => 'Proposal',
|
||||
'update' => 'Update');
|
||||
|
||||
// commands
|
||||
$lang['remove'] = 'Remove';
|
||||
$lang['update'] = 'Update';
|
||||
$lang['proposal'] = 'Proposal';
|
||||
$lang['new'] = 'Reset';
|
||||
$lang['clear'] = 'Clear cache';
|
||||
$lang['clearAll'] = 'Clear all cache';
|
||||
|
||||
// labels
|
||||
$lang['ticketIfUpdate'] = 'Ticket (if update) :';
|
||||
$lang['ticket'] = 'Ticket';
|
||||
$lang['useTicket'] = 'Use ticket';
|
||||
$lang['date'] = 'Date';
|
||||
$lang['ip'] = 'IP';
|
||||
$lang['email'] = 'e-mail';
|
||||
$lang['word'] = 'Word';
|
||||
$lang['translate'] = 'Translate';
|
||||
$lang['why'] = 'Why ?';
|
||||
$lang['poll'] = 'Poll ?';
|
||||
$lang['why'] = 'Why';
|
||||
|
||||
|
||||
// messages
|
||||
$lang['readData'] = 'Reread recording data.';
|
||||
$lang['wordMandatory'] = '"Word" mandatory.';
|
||||
$lang['translateMandatory'] = '"translate" mandatory.';
|
||||
$lang['proposalRecorded'] = 'Your proposal is actually recorded or updated with the ticket : ';
|
||||
$lang['ticketDeleted'] = ' removed.';
|
||||
$lang['pageDeleted'] = 'Page removed.';
|
||||
$lang['lastIP'] = 'It is your last proposal. We need time to study them.';
|
||||
$lang['maxIP'] = 'You send many proposals. Let us time to study them :-).';
|
||||
$lang['noDef'] = 'Definition doesn\'t exist anymore.';
|
||||
$lang['writePoll'] = 'Poll recorded.';
|
||||
$lang['glossaryNotEmpty'] = 'Can\'t remove the no-empty glossary: ';
|
||||
$lang['glossaryRemoved'] = 'Glossary removed : ';
|
||||
$lang['notPolledYet'] = 'Be the first to poll!';
|
||||
$lang['notifySubject'] = '[glossary] New proposal!';
|
||||
$lang['notifyContent'] = "New proposal:\n\nWord: @WORD@\nTranslate: @TRANSLATE@\n\n";
|
||||
$lang['badCaptcha'] = "Are you actually a human ?";
|
||||
$lang['createPage'] = 'Create page';
|
||||
|
||||
// toolTip
|
||||
$lang['tipWord'] = 'Sort by "Word';
|
||||
$lang['tipTranslate'] = 'Sort by "Translate"';
|
||||
$lang['tipDate'] = 'Sort by creation';
|
||||
$lang['tipView'] = 'Sort by view';
|
||||
$lang['tipScore'] = 'Sort by score';
|
||||
$lang['tipSearch'] = 'Search text';
|
||||
$lang['tipWhy'] = 'Click! See the amazing explanation!';
|
||||
$lang['tipPoll'] = 'Clik to see the explanation and poll.';
|
||||
$lang['tipPollDown'] = 'I poll against!';
|
||||
$lang['tipPollUp'] = 'I poll for!';
|
||||
?>
|
11
lang/en/pageTemplate.txt
Normal file
@ -0,0 +1,11 @@
|
||||
<wrap tip right>New proposition? \\ Share yours **@@PROPOSITIONPAGE@@** !</wrap>
|
||||
|
||||
====== Choisissons notre vocabulaire ======
|
||||
|
||||
@@WORD@@@@TRANSLATE@@| Your score : | {{glossary poll="@@POL@@"}} |
|
||||
TODO Give us your own @@PROPOSITIONPAGE@@ :-)
|
||||
|
||||
<WRAP center>
|
||||
{{glossary list}}
|
||||
</WRAP>
|
||||
|
19
lang/en/settings.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* @license http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html
|
||||
* @author Francois Merciol <dokuplugin@merciol.fr>
|
||||
*
|
||||
* English language file
|
||||
*/
|
||||
|
||||
// for the configuration manager
|
||||
$lang['dataDir'] = 'directory where data are placed';
|
||||
$lang['recentDays'] = 'number of days the definition is considared new';
|
||||
$lang['adminGroup'] = 'group to managed proposition and definition';
|
||||
$lang['maxIP'] = 'maximum waitting proposition per IP adresse';
|
||||
$lang['propGroup'] = 'group without limite of proposition';
|
||||
$lang['transSep'] = 'separator that cause a return in translate list';
|
||||
$lang['propositionPage'] = 'page include proposition form (main glossary page)';
|
||||
$lang['sampleDelai'] = 'Cache time delay for sample (sec)';
|
||||
$lang['sampleDelai'] = 'Cache time delay for list (sec)';
|
||||
?>
|
1
lang/en/translateTemplate.txt
Normal file
@ -0,0 +1 @@
|
||||
| Say: | <glossary one-way/> <glossary translate>@@TRANSLATE@@</glossary> |
|
1
lang/en/wordTemplate.txt
Normal file
@ -0,0 +1 @@
|
||||
| Don't say: | <glossary stop/> <glossary word>@@WORD@@</glossary> |
|
67
lang/fr/lang.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* @license http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html
|
||||
* @author Francois Merciol <dokuplugin@merciol.fr>
|
||||
*
|
||||
* French language file
|
||||
*/
|
||||
|
||||
// javascript
|
||||
$lang['js'] =
|
||||
array ('pleaseWait' => 'Connexion avec le serveur en cours ...',
|
||||
'proposal' => 'Faire un don',
|
||||
'update' => 'Mise à jour');
|
||||
|
||||
// commands
|
||||
$lang['remove'] = 'Supprime';
|
||||
$lang['update'] = 'Mise à jour';
|
||||
$lang['proposal'] = 'Faire un don';
|
||||
$lang['new'] = 'Recommencer';
|
||||
$lang['clear'] = 'Effacer le cache';
|
||||
$lang['clearAll'] = 'Effacer tous les caches';
|
||||
|
||||
// labels
|
||||
$lang['ticketIfUpdate'] = 'Ticket (si modification) :';
|
||||
$lang['ticket'] = 'Ticket';
|
||||
$lang['useTicket'] = 'Utilise ticket';
|
||||
$lang['date'] = 'Date';
|
||||
$lang['ip'] = 'IP';
|
||||
$lang['email'] = 'Mel';
|
||||
$lang['word'] = 'Ne dites plus !';
|
||||
$lang['translate'] = 'Dites !';
|
||||
$lang['why'] = '?';
|
||||
$lang['poll'] = 'Avis';
|
||||
$lang['createPage'] = 'Création de page';
|
||||
|
||||
// messages
|
||||
$lang['readData'] = 'Relecture des données enregistrées.';
|
||||
$lang['wordMandatory'] = '"Ne dites plus !" nécessaire.';
|
||||
$lang['translateMandatory'] = '"Dites !" nécessaire.';
|
||||
$lang['proposalRecorded'] = 'Votre don est bien enregistré (donnez nous du temps pour l\'étudier).<br/>'.
|
||||
'Il faut cliquer sur "Recommencer" pour un nouveau ticket et ne pas perdre ce don.<br/>'.
|
||||
'Pour modifier votre demande, voici votre ticket : ';
|
||||
$lang['ticketDeleted'] = ' supprimé.';
|
||||
$lang['pageDeleted'] = 'Page supprimée.';
|
||||
$lang['lastIP'] = 'C\'est votre dernier don. Il faut nous laisser le temps de les étudier :-).';
|
||||
$lang['maxIP'] = 'Vous avez fait beaucoup de dons. Laissez-nous le temps de les étudier :-).';
|
||||
$lang['noDef'] = 'La définition n\'éxiste plus.';
|
||||
$lang['writePoll'] = 'Avis enregistré.';
|
||||
$lang['glossaryNotEmpty'] = 'Impossible de supprimer le glossaire non vide : ';
|
||||
$lang['glossaryRemoved'] = 'Glossaire supprimé : ';
|
||||
$lang['notPolledYet'] = 'Soyez le 1er à donner votre avis !';
|
||||
$lang['notifySubject'] = '[glossaire] Une nouvelle proposition !';
|
||||
$lang['notifyContent'] = "Une nouvelle proposition :\n\nNe dites plus : @WORD@\nDites : @TRANSLATE@\n\n";
|
||||
$lang['badCaptcha'] = "Etes-vous vraiment un humain ?";
|
||||
|
||||
// toolTip
|
||||
$lang['tipWord'] = 'Tri par "Ne dites plus !"';
|
||||
$lang['tipTranslate'] = 'Tri par "Dites !"';
|
||||
$lang['tipDate'] = 'Tri par dates';
|
||||
$lang['tipView'] = 'Tri par vues';
|
||||
$lang['tipScore'] = 'Tri par avis';
|
||||
$lang['tipSearch'] = 'Recherche le texte';
|
||||
$lang['tipWhy'] = 'Un simple clic et<br/>l\'explication déchire !';
|
||||
$lang['tipPoll'] = 'Un clic pour :<br/> voir l\'explication,<br/> et donner un avis.';
|
||||
$lang['tipPollDown'] = 'J\'aime pas !<br/>Juste un clic pour le dire.';
|
||||
$lang['tipPollUp'] = 'J\'aime !<br/>Juste un clic pour le dire.';
|
||||
?>
|
11
lang/fr/pageTemplate.txt
Normal file
@ -0,0 +1,11 @@
|
||||
<wrap tip right>Une idée d'expression ? \\ Partagez-la par un **@@PROPOSITIONPAGE@@** !</wrap>
|
||||
|
||||
====== Choisissons notre vocabulaire ======
|
||||
|
||||
@@WORD@@@@TRANSLATE@@| Votre avis : | {{glossary poll="@@POL@@"}} |
|
||||
TODO Votre @@PROPOSITIONPAGE@@ nous intéresse :-)
|
||||
|
||||
<WRAP center>
|
||||
{{glossary list}}
|
||||
</WRAP>
|
||||
|
19
lang/fr/settings.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
/**
|
||||
* @license http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html
|
||||
* @author Francois Merciol <dokuplugin@merciol.fr>
|
||||
*
|
||||
* French language file
|
||||
*/
|
||||
|
||||
// for the configuration manager
|
||||
$lang['dataDir'] = 'répertoire où sont placer les données';
|
||||
$lang['recentDays'] = 'nombre de jours pendant lesquels la définition est considéré comme récente';
|
||||
$lang['adminGroup'] = 'groupe de gestion des propositions et des définitions';
|
||||
$lang['maxIP'] = 'nombre maximum de proposition en attente par adresse IP';
|
||||
$lang['propGroup'] = 'groupe sans limite de proposition';
|
||||
$lang['transSep'] = 'spérateur de qui implique un retour à la ligne dans la liste des traductions';
|
||||
$lang['propositionPage'] = 'page où se trouve le formulaire de proposition (acceuil du glossaire)';
|
||||
$lang['sampleDelai'] = 'Temps de cache pour l\'exemple (en secondes)';
|
||||
$lang['listDelai'] = 'Temps de cache pour la liste (en secondes)';
|
||||
?>
|
1
lang/fr/translateTemplate.txt
Normal file
@ -0,0 +1 @@
|
||||
| Dites : | <glossary one-way/> <glossary translate>@@TRANSLATE@@</glossary> |
|
1
lang/fr/wordTemplate.txt
Normal file
@ -0,0 +1 @@
|
||||
| Ne dites plus : | <glossary stop/> <glossary word>@@WORD@@</glossary> |
|
7
plugin.info.txt
Normal file
@ -0,0 +1,7 @@
|
||||
base glossary
|
||||
author Francois Merciol
|
||||
email dokuplugin@merciol.fr
|
||||
date 2019-09-25
|
||||
name Glossary Plugin
|
||||
desc Managed glossary
|
||||
url http://www.dokuwiki.org/plugin:glossary
|
227
script.js
Normal file
@ -0,0 +1,227 @@
|
||||
/**
|
||||
* @license http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html
|
||||
* @author Francois Merciol <dokuplugin@merciol.fr>
|
||||
*
|
||||
* Javascript functionality for the glossary plugin
|
||||
*/
|
||||
|
||||
// ========================================
|
||||
// Util
|
||||
// ========================================
|
||||
function trim (str) {
|
||||
return str.replace(/^\s+/g,'').replace(/\s+$/g,'') ;
|
||||
}
|
||||
|
||||
function glossaryClearMsgJ (item) {
|
||||
// efface le popup
|
||||
item.closest ("div").find ("div.popup").each (function () {
|
||||
jQuery (this).remove ();
|
||||
});
|
||||
}
|
||||
|
||||
function glossaryZebraJ (jTable) {
|
||||
// alterne les couleurs des lignes du tableau
|
||||
var oddEven = new Array ("odd", "even");
|
||||
var even = 0;
|
||||
jTable.find ("tr").each (function () {
|
||||
var item = jQuery (this);
|
||||
if (item.hasClass ("title"))
|
||||
return;
|
||||
if (item.css ("display") == "none")
|
||||
return;
|
||||
this.className = oddEven [even];
|
||||
even = 1 - even;
|
||||
});
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Clear form
|
||||
// ========================================
|
||||
function glossaryReset (input) {
|
||||
|
||||
// met à blanc le formulaire
|
||||
var jForm = jQuery (input).closest ("form");
|
||||
jForm.find ("input[type=text]").each (function () {
|
||||
this.defaultValue = "";
|
||||
jQuery (this).val ("");
|
||||
});
|
||||
jForm.find ("input[type=textarea]").each (function () {
|
||||
this.defaultValue = "";
|
||||
jQuery (this).val ("");
|
||||
});
|
||||
glossaryClearMsgJ (jForm);
|
||||
}
|
||||
|
||||
function glossaryUpdateProposalLabel (form) {
|
||||
form.elements[4].value = LANG["plugins"]["glossary"][form.elements[7].value ? "update" : "proposal"];
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Glossary Util
|
||||
// ========================================
|
||||
function glossaryComparatorWord (a, b) {
|
||||
return glossaryComparator (a, b, "word", false);
|
||||
}
|
||||
|
||||
function glossaryComparatorTranslate (a, b) {
|
||||
return glossaryComparator (a, b, "translate", false);
|
||||
}
|
||||
|
||||
function glossaryComparatorDate (a, b) {
|
||||
return -glossaryComparator (a, b, "date", false);
|
||||
}
|
||||
|
||||
function glossaryComparatorView (a, b) {
|
||||
return -glossaryComparator (a, b, "view", true);
|
||||
}
|
||||
|
||||
function glossaryComparatorScore (a, b) {
|
||||
return -glossaryComparator (a, b, "score", false);
|
||||
}
|
||||
|
||||
function glossaryComparator (a, b, name, num) {
|
||||
var valA = "";
|
||||
for (var i = 0; i < a.attributes.length; i++)
|
||||
if (a.attributes [i].name == name) {
|
||||
valA = a.attributes [i].nodeValue;
|
||||
break;
|
||||
}
|
||||
var valB = "";
|
||||
for (var i = 0; i < b.attributes.length; i++)
|
||||
if (b.attributes [i].name == name) {
|
||||
valB = b.attributes [i].nodeValue;
|
||||
break;
|
||||
}
|
||||
if (num) {
|
||||
if (!valA)
|
||||
valA = 0;
|
||||
if (!valB)
|
||||
valB = 0;
|
||||
return parseInt (valA) - parseInt (valB);
|
||||
}
|
||||
if (valB == valA)
|
||||
return 0;
|
||||
if (valB > valA)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
function glossaryGetRowsJ (jTable) {
|
||||
// prend les lignes du tableau
|
||||
var result = new Array ();
|
||||
jTable.find ("tr").each (function () {
|
||||
if (jQuery (this).hasClass ("title"))
|
||||
return;
|
||||
result.push (this);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
function glossarySetRowsJ (jTable, rows) {
|
||||
// fixe les lignes du tableau
|
||||
var titles = new Array ();
|
||||
jTable.children ().not ("tr").each (function () {
|
||||
titles.push (this);
|
||||
});
|
||||
jTable.children (".title").each (function () {
|
||||
titles.push (this);
|
||||
});
|
||||
jTable.empty ();
|
||||
for (var i in titles)
|
||||
jTable.append (titles [i]);
|
||||
for (var i in rows)
|
||||
jTable.append (rows [i]);
|
||||
}
|
||||
|
||||
function glossarySort (input, comparator) {
|
||||
// trie le tableau
|
||||
var jTable = jQuery (input).closest ("tr").parent ();
|
||||
var rows = glossaryGetRowsJ (jTable);
|
||||
if (rows.length < 2)
|
||||
return;
|
||||
rows.sort (comparator);
|
||||
glossarySetRowsJ (jTable, rows);
|
||||
glossaryZebraJ (jTable);
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// focus table
|
||||
// ========================================
|
||||
function glossarySearch (input) {
|
||||
// filtre les lignes du tableau
|
||||
var jInput = jQuery (input);
|
||||
glossaryClearMsgJ (jInput);
|
||||
var value = trim (jInput.val ()).toLowerCase ();
|
||||
var jTable = jInput.closest ("tr").parent ();
|
||||
jTable.find ("tr").each (function () {
|
||||
var item = jQuery (this);
|
||||
if (item.hasClass ("title"))
|
||||
return;
|
||||
item.css ("display", "");
|
||||
if (!value)
|
||||
return;
|
||||
var hidden = true;
|
||||
item.find ("td.word,td.translate").each (function () {
|
||||
if (this.textContent && this.textContent.toLowerCase ().indexOf (value) >= 0)
|
||||
hidden = false;
|
||||
});
|
||||
if (hidden)
|
||||
item.css ("display", "none");
|
||||
});
|
||||
glossaryZebraJ (jTable);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// sending form
|
||||
// ========================================
|
||||
function glossaryPoll (ancor, ticket, opinion, NS) {
|
||||
// vote
|
||||
var params = "glossary[operation]=poll&glossary[ticket]="+ticket+"&glossary[opinion]="+opinion+"&glossary[ns]="+NS;
|
||||
glossarySend (ancor, DOKU_BASE+"lib/plugins/glossary/ajax.php", params);
|
||||
}
|
||||
|
||||
function glossaryAjax (form) {
|
||||
var params = "";
|
||||
for (var idx = 0; idx < form.elements.length; idx++) {
|
||||
var elem = form.elements[idx];
|
||||
if (elem.type == "checkbox") {
|
||||
if (elem.checked)
|
||||
params += "&"+elem.name+"="+elem.value;
|
||||
} else
|
||||
params += "&"+elem.name+"="+elem.value;
|
||||
}
|
||||
glossarySend (form, DOKU_BASE+"lib/plugins/glossary/ajax.php", params);
|
||||
return false;
|
||||
}
|
||||
function glossarySendClear (action, ns) {
|
||||
jQuery.ajax ({
|
||||
type: "POST",
|
||||
url: DOKU_BASE+"lib/plugins/glossary/ajax.php",
|
||||
cache: false,
|
||||
async: true,
|
||||
data: "glossary[action]="+action+"&glossary[ns]="+ns,
|
||||
});
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Ajax function
|
||||
// ========================================
|
||||
function glossarySend (sender, uri, params) {
|
||||
var jDiv = jQuery (sender).closest ("div");
|
||||
glossaryClearMsgJ (jQuery (sender));
|
||||
jQuery ('<div class="popup">'+LANG["plugins"]["glossary"]["pleaseWait"]+'</div>').
|
||||
insertBefore (jDiv.children ().first ());
|
||||
jQuery.ajax ({
|
||||
type: "POST",
|
||||
url: uri,
|
||||
cache: false,
|
||||
async: true,
|
||||
data: params,
|
||||
success: function (response) {
|
||||
jDiv.html (trim (response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ========================================
|
150
style.css
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* @license http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html
|
||||
* @author Francois <webmestre@parlenet.org>
|
||||
*/
|
||||
|
||||
/* ==================== */
|
||||
body {
|
||||
counter-reset: glossary;
|
||||
}
|
||||
|
||||
div.glossary table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
div.glossary table tr {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.glossary table tr.title {
|
||||
background-color: #DDF;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.glossary table tr.odd {
|
||||
}
|
||||
|
||||
div.glossary table tr.even {
|
||||
background-color: #DDD;
|
||||
}
|
||||
|
||||
div.glossary table th,
|
||||
div.glossary table td {
|
||||
margin: 2px 4px;
|
||||
padding: 2px 4px;
|
||||
}
|
||||
|
||||
div.glossary table input.text {
|
||||
width: 20em;
|
||||
}
|
||||
|
||||
span.glossaryWord,
|
||||
span.glossaryWord a.wikilink1:visited,
|
||||
span.glossaryWord a.wikilink1:link {
|
||||
color: #FE0000 !important;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.glossaryTranslate,
|
||||
span.glossaryTranslate a.wikilink1:visited,
|
||||
span.glossaryTranslate a.wikilink1:link {
|
||||
color: #004C9A !important;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.glossary table th {
|
||||
counter-reset: ch1;
|
||||
}
|
||||
|
||||
div.glossary table td.count:before {
|
||||
counter-increment: glossary;
|
||||
content: counter(glossary) " ";
|
||||
}
|
||||
|
||||
div.glossary table td.count {
|
||||
color: #BBB;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.glossary table td.word,
|
||||
div.glossary table td.word a:visited,
|
||||
div.glossary table td.word a:link {
|
||||
color: #FE0000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.glossary table td.translate,
|
||||
div.glossary table td.translate a:visited,
|
||||
div.glossary table td.translate a:link {
|
||||
color: #004C9A;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.glossary table textarea.why {
|
||||
width: 50em;
|
||||
height: 6em;
|
||||
}
|
||||
|
||||
div.glossary table td.poll {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
div.glossary table td.right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.glossary .popup {
|
||||
position: absolute;
|
||||
top: auto;
|
||||
left: auto;
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin: 1em;
|
||||
padding: 1em;
|
||||
overflow: visible;
|
||||
z-index: 50;
|
||||
opacity: 0.7;
|
||||
background: #EDDB31;
|
||||
color: black;
|
||||
border: 1px solid #AE090D;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.glossary .toolTip a,
|
||||
div.glossary .toolTip form {
|
||||
cursor: help;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
div.glossary .toolTip a span,
|
||||
div.glossary .toolTip form span {
|
||||
position: absolute;
|
||||
z-index: 50;
|
||||
top: -2000em;
|
||||
left: -2000em;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
opacity: 0.8;
|
||||
border: 1px solid #AE090D;
|
||||
background-color: #EDDB31;
|
||||
color: #AE090D;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
div.glossary .toolTip a:hover span,
|
||||
div.glossary .toolTip form:hover span {
|
||||
top: auto;
|
||||
left: auto;
|
||||
left: auto;
|
||||
width: auto;
|
||||
height: auto;
|
||||
overflow: visible;
|
||||
margin-top: 2em;
|
||||
margin-left: 0em;
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
/* ==================== */
|
119
syntax/div.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
/**
|
||||
* @license http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html
|
||||
* @author Francois Merciol <dokuplugin@merciol.fr>
|
||||
*
|
||||
* 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/');
|
||||
require_once(DOKU_PLUGIN.'syntax.php');
|
||||
|
||||
require_once (dirname (__FILE__).'/../glossary.class.php');
|
||||
|
||||
// ============================================================
|
||||
class syntax_plugin_glossary_div extends DokuWiki_Syntax_Plugin {
|
||||
|
||||
// ============================================================
|
||||
function getType () { return 'substition'; }
|
||||
function getPType () { return 'block'; }
|
||||
function getAllowedTypes () { return array ('container', 'baseonly', 'formatting', 'substition', 'protected', 'disabled', 'paragraphs'); }
|
||||
function getSort () { return 309; }
|
||||
function connectTo ($mode) {
|
||||
$this->Lexer->addSpecialPattern ('\{\{glossary[^}]*\}\}', $mode, 'plugin_glossary_div');
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function handle ($match, $state, $pos, Doku_Handler $handler) {
|
||||
switch ($state) {
|
||||
case DOKU_LEXER_SPECIAL :
|
||||
return array ($state, trim (substr ($match, 10, -2))); // "{{glossary" => 10 "}}" => 2
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function render ($mode, Doku_Renderer $renderer, $indata) {
|
||||
if ($mode != 'xhtml')
|
||||
return false;
|
||||
list ($state, $data) = $indata;
|
||||
$data = " ".$data." ";
|
||||
$renderer->info ['cache'] = FALSE;
|
||||
$cmd = "";
|
||||
$arg = "";
|
||||
|
||||
if (preg_match_all ("#(\"[^\"]*\")* help (\"[^\"]*\")*#", strtolower ($data), $dumy) > 0) {
|
||||
$this->help ($renderer);
|
||||
return true;
|
||||
}
|
||||
// namespace
|
||||
global $ID;
|
||||
$ns = getNS ($ID);
|
||||
if (preg_match_all ("#>([^ ]*) .*#", strtolower ($data), $dumy) > 0) {
|
||||
$ns = $dumy[1][0];
|
||||
if (($ns == '*') || ($ns == ':'))
|
||||
$ns = '';
|
||||
elseif ($ns == '.')
|
||||
$ns = getNS ($ID);
|
||||
else
|
||||
$ns = cleanID ($ns);
|
||||
}
|
||||
if (preg_match_all ("#(\"[^\"]*\")* sample (\"[^\"]*\")*#", strtolower ($data), $dumy) > 0)
|
||||
$cmd = "printSample";
|
||||
elseif (preg_match_all ("#(\"[^\"]*\")* list (\"[^\"]*\")*#", strtolower ($data), $dumy) > 0)
|
||||
$cmd = "printList";
|
||||
elseif (preg_match_all ("#(\"[^\"]*\")* poll=\"(?<word>[^\"]*)\" (\"[^\"]*\")*#", $data, $dumy) > 0) {
|
||||
$cmd = "printPoll";
|
||||
$arg = $dumy['word'][0];
|
||||
} elseif (preg_match_all ("#(\"[^\"]*\")* proposal (\"[^\"]*\")*#", strtolower ($data), $dumy) > 0)
|
||||
$cmd = "printProposal";
|
||||
elseif (preg_match_all ("#(\"[^\"]*\")* admin-proposal (\"[^\"]*\")*#", strtolower ($data), $dumy) > 0)
|
||||
$cmd = "adminProposal";
|
||||
elseif (preg_match_all ("#(\"[^\"]*\")* admin-definition (\"[^\"]*\")*#", strtolower ($data), $dumy) > 0)
|
||||
$cmd = "adminDefinition";
|
||||
elseif (preg_match_all ("#(\"[^\"]*\")* admin-glossaries (\"[^\"]*\")*#", strtolower ($data), $dumy) > 0)
|
||||
$cmd = "adminGlossaries";
|
||||
else {
|
||||
$this->help ($renderer);
|
||||
return true;
|
||||
}
|
||||
|
||||
$glossary = new glossary ($this, $ns);
|
||||
ob_start ();
|
||||
$glossary->$cmd ($arg);
|
||||
$text = ob_get_contents();
|
||||
ob_end_clean ();
|
||||
foreach ($glossary->message as $type => $msg)
|
||||
$text = '<div class="'.$type.'">'.$msg.'</div>'.$text;
|
||||
$renderer->doc .= '<div class="glossary">'.$text.'</div>';
|
||||
return true;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function isAdmin () {
|
||||
global $INFO;
|
||||
return
|
||||
isset ($INFO ['userinfo']) &&
|
||||
isset ($INFO ['userinfo']['grps']) &&
|
||||
in_array (trim ($this->getConf ('adminGroup')), $INFO ['userinfo']['grps']);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function help (Doku_Renderer $renderer) {
|
||||
$url = "http://admin.parlenet.org/plugins/glossary/";
|
||||
$renderer->doc .=
|
||||
' <h1>Help Glossary</h1>'.NL.
|
||||
' <ul>'.NL.
|
||||
' <li><b>{{glossary></b>namespace [help] (sample|list|proposal|admin-proposal|admin-definition|admin-glossaries)<b>}}</b></li>'.NL.
|
||||
' <li><b><glossary</b> (help|clock|face-smile|face-sad|stop|one-way|search) <b>/></b></li>'.NL.
|
||||
' <li><b><glossary</b> (word|translate) <b>></b> ... <b></glossary></b></li>'.NL.
|
||||
' </ul>'.NL.
|
||||
' <p><a class="urlextern" rel="nofollow" title="'.$url.'" href="'.$url.'">'.$url.'</a></p>'.NL;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
} // syntax_plugin_GLOSSARY
|
||||
?>
|
131
syntax/span.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
/**
|
||||
* @license http://www.cecill.info/licences/Licence_CeCILL-B_V1-fr.html
|
||||
* @author Francois Merciol <dokuplugin@merciol.fr>
|
||||
*
|
||||
* 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/');
|
||||
require_once (DOKU_PLUGIN.'syntax.php');
|
||||
|
||||
require_once (dirname (__FILE__).'/../glossary.class.php');
|
||||
|
||||
// ============================================================
|
||||
class syntax_plugin_glossary_span extends DokuWiki_Syntax_Plugin {
|
||||
|
||||
// ============================================================
|
||||
function getType () { return 'formatting'; }
|
||||
function getPType () { return 'normal'; }
|
||||
function getAllowedTypes() { return array ('formatting', 'substition', 'disabled'); }
|
||||
function getSort () { return 195; }
|
||||
function accepts ($mode) {
|
||||
if ($mode == substr (get_class ($this), 7))
|
||||
return true;
|
||||
return parent::accepts ($mode);
|
||||
}
|
||||
|
||||
function connectTo ($mode) {
|
||||
$this->Lexer->addSpecialPattern ('<glossary[^/]*?/>', $mode, 'plugin_glossary_span');
|
||||
$this->Lexer->addEntryPattern ('<glossary[^/]*?>(?=.*?</glossary>)', $mode, 'plugin_glossary_span');
|
||||
}
|
||||
function postConnect() {
|
||||
$this->Lexer->addExitPattern ('</glossary>', 'plugin_glossary_span');
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function handle ($match, $state, $pos, Doku_Handler $handler) {
|
||||
switch ($state) {
|
||||
case DOKU_LEXER_SPECIAL :
|
||||
$data = strtolower (trim (substr ($match, 9, -2)));
|
||||
return array ($state, $data);
|
||||
case DOKU_LEXER_ENTER:
|
||||
$data = strtolower (trim (substr ($match, 9, -1)));
|
||||
return array ($state, $data);
|
||||
|
||||
case DOKU_LEXER_UNMATCHED :
|
||||
$handler->_addCall ('cdata', array ($match), $pos);
|
||||
return false;
|
||||
|
||||
case DOKU_LEXER_EXIT :
|
||||
return array ($state, '');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
function render ($mode, Doku_Renderer $renderer, $indata) {
|
||||
if (empty ($indata))
|
||||
return false;
|
||||
if ($mode != 'xhtml')
|
||||
false;
|
||||
list ($state, $data) = $indata;
|
||||
$data = trim ($data);
|
||||
switch ($state) {
|
||||
case DOKU_LEXER_SPECIAL :
|
||||
$imgDir = DOKU_REL.'lib/plugins/glossary/images/';
|
||||
if ($data == "help")
|
||||
$renderer->doc .= '<img src="'.$imgDir.'help.png" />';
|
||||
elseif ($data == "clock")
|
||||
$renderer->doc .= '<img src="'.$imgDir.'clock.png" />';
|
||||
elseif ($data == "face-smile")
|
||||
$renderer->doc .= '<img src="'.$imgDir.'face-smile.png" />';
|
||||
elseif ($data == "face-sad")
|
||||
$renderer->doc .= '<img src="'.$imgDir.'face-sad.png" />';
|
||||
elseif ($data == "stop")
|
||||
$renderer->doc .= '<img src="'.$imgDir.'stop.png" />';
|
||||
elseif ($data == "one-way")
|
||||
$renderer->doc .= '<img src="'.$imgDir.'one-way.png" />';
|
||||
elseif ($data == "eye")
|
||||
$renderer->doc .= '<img src="'.$imgDir.'eye.png" />';
|
||||
elseif ($data == "score")
|
||||
$renderer->doc .= '<img src="'.$imgDir.'score-all.png" width="32" />';
|
||||
elseif ($data == "search")
|
||||
$renderer->doc .= '<img src="'.$imgDir.'search.png" />';
|
||||
elseif (preg_match_all ("#(?<ns>.*)\s+(?<type>definition|proposal|poll)#", $data, $dumy) > 0) {
|
||||
global $ID;
|
||||
$ns = getNS ($ID);
|
||||
if (count ($dumy ['ns']) > 0) {
|
||||
$ns = $dumy['ns'][0];
|
||||
if (($ns == '*') || ($ns == ':'))
|
||||
$ns = '';
|
||||
elseif ($ns == '.')
|
||||
$ns = getNS ($ID);
|
||||
else
|
||||
$ns = cleanID ($ns);
|
||||
}
|
||||
$glossary = new glossary ($this, $ns);
|
||||
switch ($dumy['type'][0]) {
|
||||
case "definition":
|
||||
$renderer->doc .= $glossary->getDefinitionSize ();
|
||||
break;
|
||||
case "proposal":
|
||||
$renderer->doc .= $glossary->getProposalSize ();
|
||||
break;
|
||||
case "poll":
|
||||
$renderer->doc .= $glossary->getPollSize ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DOKU_LEXER_ENTER:
|
||||
if ($data == "word")
|
||||
$renderer->doc .= '<span class="glossaryWord">';
|
||||
elseif ($data == "translate")
|
||||
$renderer->doc .= '<span class="glossaryTranslate">';
|
||||
else
|
||||
$renderer->doc .= '<span>';
|
||||
break;
|
||||
case DOKU_LEXER_EXIT:
|
||||
$renderer->doc .= "</span>";
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
} // syntax_plugin_GLOSSARY
|
||||
?>
|