@ -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. |
|||
|
|||
|
@ -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); |
|||
} |
|||
} |
|||
?> |
@ -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; |
|||
?> |
@ -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'); |
|||
?> |
@ -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 (); |
|||
} |
|||
} |
|||
|
|||
// ============================================================ |
|||
} |
After Width: | Height: | Size: 1004 B |
After Width: | Height: | Size: 666 B |
After Width: | Height: | Size: 802 B |
After Width: | Height: | Size: 806 B |
After Width: | Height: | Size: 897 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 772 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 772 B |
After Width: | Height: | Size: 783 B |
After Width: | Height: | Size: 872 B |
@ -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!'; |
|||
?> |
@ -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> |
|||
|
@ -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)'; |
|||
?> |
@ -0,0 +1 @@ |
|||
| Say: | <glossary one-way/> <glossary translate>@@TRANSLATE@@</glossary> | |
@ -0,0 +1 @@ |
|||
| Don't say: | <glossary stop/> <glossary word>@@WORD@@</glossary> | |
@ -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.'; |
|||
?> |
@ -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> |
|||
|
@ -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)'; |
|||
?> |
@ -0,0 +1 @@ |
|||
| Dites : | <glossary one-way/> <glossary translate>@@TRANSLATE@@</glossary> | |
@ -0,0 +1 @@ |
|||
| Ne dites plus : | <glossary stop/> <glossary word>@@WORD@@</glossary> | |
@ -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 |
@ -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)); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
// ========================================
|
@ -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; |
|||
} |
|||
|
|||
/* ==================== */ |
@ -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 |
|||
?> |
@ -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 |
|||
?> |