this isn't yet a plugin, but a quick, unstable hack.
Once installed, under the edit box appears a list of media files attached to this page.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<?php
/**
* DokuWiki Template
*
* This is the template for the media ATTACHED selection iframe.
*
* You should leave the doctype at the very top - It should
* always be the very first line of a document.
*
* @link http://www.dokuwiki.org/wiki:tpl:templates
* @author Andreas Gohr <andi@splitbrain.org>
*
*/
?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?php echo $conf['lang']?>" lang="<?php echo $conf['lang']?>" dir="ltr">
<head>
<title><?php echo hsc($lang['mediaselect'])?> [<?php echo hsc($conf['title'])?>]</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<?php tpl_metaheaders()?>
<link rel="shortcut icon" href="<?php echo DOKU_BASE?>lib/images/favicon.ico" />
<link rel="stylesheet" media="screen" type="text/css" href="<?php echo DOKU_TPL?>layout.css" />
<link rel="stylesheet" media="screen" type="text/css" href="<?php echo DOKU_TPL?>design.css" />
<!--[if gte IE 5]>
<style type="text/css">
/* that IE 5+ conditional comment makes this only visible in IE 5+ */
/* IE bugfix for transparent PNGs */
//DISABLED img { behavior: url("<?php echo DOKU_BASE?>lib/scripts/pngbehavior.htc"); }
</style>
<![endif]-->
</head>
<body>
<div class="dokuwiki">
<?php html_msgarea()?>
<br />
<div class="mediaselect">
<div class="mediaselect-right">
<h2>Anhänge</h2>
Ein Bild anzeigen: <br />
{{<?php echo hsc($NS)?>:meinbild.jpg}}<br />
Alle angehängten Bilder anzeigen: <br />
{{gallery><?php echo hsc($NS)?>}}<p>
<hr />
<?php tpl_mediafilelist_attached()?>
<div class="uploadform">
<?php tpl_mediauploadform_attached()?>
</div>
</div>
</div>
</div>
</body>
</html>
<?php
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/lang/en/lang.php');
require_once(DOKU_INC.'inc/lang/'.$conf['lang'].'/lang.php');
require_once(DOKU_INC.'inc/html.php');
require_once(DOKU_INC.'inc/JpegMeta.php');
require_once(DOKU_INC.'inc/search.php');
require_once(DOKU_INC.'inc/template.php');
require_once(DOKU_INC.'inc/auth.php');
//close sesseion
session_write_close();
//get namespace to display (either direct or from deletion order)
if($_REQUEST['delete']){
$DEL = cleanID($_REQUEST['delete']);
$NS = getNS($DEL);
}elseif($_REQUEST['edit']){
$IMG = cleanID($_REQUEST['edit']);
$SRC = mediaFN($IMG);
$NS = getNS($IMG);
}else{
$NS = $_REQUEST['ns'];
$NS = cleanID($NS);
}
//check upload permissions
$AUTH = auth_quickaclcheck("$NS:*");
if($AUTH >= AUTH_UPLOAD){
$UPLOADOK = true;
//create the given namespace (just for beautification)
$mdir = $conf['mediadir'].'/'.utf8_encodeFN(str_replace(':','/',$NS));
io_makeFileDir("$mdir/xxx");
}else{
$UPLOADOK = false;
}
//handle deletion
$mediareferences = array();
if($DEL && $AUTH >= AUTH_DELETE){
if($conf['refcheck']){
search($mediareferences,$conf['datadir'],'search_reference',array('query' => $DEL));
}
if(!count($mediareferences)){
media_delete($DEL);
}elseif(!$conf['refshow']){
msg(str_replace('%s',noNS($DEL),$lang['mediainuse']),0);
}
}
//handle metadatasaving
if($UPLOADOK && $SRC && $_REQUEST['save']){
media_metasave($SRC,$_REQUEST['meta']);
}
//handle upload
if($_FILES['upload']['tmp_name'] && $UPLOADOK){
media_upload($NS,$AUTH);
}
//start output and load template
header('Content-Type: text/html; charset=utf-8');
if($conf['refshow'] && count($mediareferences)){
include(template('mediaref.php'));
}elseif($IMG){
include(template('mediaedit.php'));
}else{
include(template('media_attached.php'));
}
//restore old umask
umask($conf['oldumask']);
/**********************************************/
/**
* Deletes mediafiles - Auth is not handled here!
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function media_delete($delid){
global $lang;
$file = mediaFN($delid);
if(@unlink($file)){
msg(str_replace('%s',noNS($delid),$lang['deletesucc']),1);
return true;
}
//something went wrong
msg(str_replace('%s',$file,$lang['deletefail']),-1);
return false;
}
/**
* Handles Mediafile uploads
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function media_upload($NS,$AUTH){
require_once(DOKU_INC.'inc/confutils.php');
global $lang;
global $conf;
// get file
$id = $_POST['id'];
$file = $_FILES['upload'];
// get id
if(empty($id)) $id = $file['name'];
$id = cleanID($NS.':'.$id);
// get filename
$fn = mediaFN($id);
// get filetype regexp
$types = array_keys(getMimeTypes());
$types = array_map(create_function('$q','return preg_quote($q,"/");'),$types);
$regex = join('|',$types);
// we set the umask here but this doesn't really help
// because a temp file was created already
umask($conf['umask']);
if(preg_match('/\.('.$regex.')$/i',$fn)){
//check for overwrite
if(@file_exists($fn) && (!$_POST['ow'] || $AUTH < AUTH_DELETE)){
msg($lang['uploadexist'],0);
return false;
}
// prepare directory
io_makeFileDir($fn);
if(move_uploaded_file($file['tmp_name'], $fn)) {
// set the correct permission here
chmod($fn, 0777 - $conf['umask']);
msg($lang['uploadsucc'],1);
return true;
}else{
msg($lang['uploadfail'],-1);
}
}else{
msg($lang['uploadwrong'],-1);
}
return false;
}
/**
* Userfunction for html_buildlist
*
* Prints available media namespaces
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function media_html_list_namespaces($item){
$ret = '';
$ret .= '<a href="'.DOKU_BASE.'lib/exe/media.php?ns='.idfilter($item['id']).'" class="idx_dir">';
$pos = strrpos($item['id'], ':');
$ret .= substr($item['id'], $pos > 0 ? $pos + 1 : 0);
$ret .= '</a>';
return $ret;
}
/**
* Saves image meta data
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
function media_metasave($src,$data){
global $lang;
$meta = new JpegMeta($src);
$meta->_parseAll();
foreach($data as $key => $val){
$val=trim($val);
if(empty($val)){
$meta->deleteField($key);
}else{
$meta->setField($key,$val);
}
}
if($meta->save()){
msg($lang['metasaveok'],1);
}else{
msg($lang['metasaveerr'],-1);
}
}
?>
inc/html.php – in function html_edit
<table><tr><td> <iframe class="mediaselect_attached" id="mediaselect1" src="lib/exe/media_attached.php?ns=<?php echo $ID; ?>" height="320" width="600" ></iframe> </td> </tr> </table>
inc/template.php – after function tpl_mediauploadform()
function tpl_mediauploadform_attached(){
global $NS;
global $UPLOADOK;
global $AUTH;
global $lang;
if(!$UPLOADOK) return;
ptln('<form action="'.DOKU_BASE.'lib/exe/media_attached.php" name="upload"'.
' method="post" enctype="multipart/form-data">',2);
ptln($lang['txt_upload'].':<br />',4);
ptln('<input type="file" name="upload" class="edit" onchange="suggestWikiname();" />',4);
ptln('<input type="hidden" name="ns" value="'.hsc($NS).'" /><br />',4);
ptln($lang['txt_filename'].'<br />',4);
ptln('<input type="text" name="id" class="edit" />',4);
ptln('<input type="submit" class="button" value="'.$lang['btn_upload'].'" accesskey="s" />',4);
if($AUTH >= AUTH_DELETE){
ptln('<label for="ow" class="simple"><input type="checkbox" name="ow" value="1" id="ow">'.$lang['txt_overwrt'].'</label>',4);
}
ptln('</form>',2);
}
inc/template.php – after function tpl_mediafilelist()
function tpl_mediafilelist_attached(){
global $conf;
global $lang;
global $NS;
global $AUTH;
$dir = utf8_encodeFN(str_replace(':','/',$NS));
$data = array();
search($data,$conf['mediadir'],'search_media',array(),$dir);
if(!count($data)){
ptln('<div class="nothing">'.$lang['nothingfound'].'</div>');
return;
}
ptln('<ul>',2);
foreach($data as $item){
ptln('<li>',4);
ptln('<a href="javascript:mediaSelect_attached(\''.$item['id'].'\')">'.
utf8_decodeFN($item['file']).
'</a>',6);
//prepare deletion button
if($AUTH >= AUTH_DELETE){
$ask = $lang['del_confirm'].'\\n';
$ask .= $item['id'];
$del = '<a href="'.DOKU_BASE.'lib/exe/media.php?delete='.urlencode($item['id']).'" '.
'onclick="return confirm(\''.$ask.'\')" onkeypress="return confirm(\''.$ask.'\')">'.
'<img src="'.DOKU_BASE.'lib/images/del.png" alt="'.$lang['btn_delete'].'" '.
'align="bottom" title="'.$lang['btn_delete'].'" /></a>';
}else{
$del = '';
}
if($item['isimg']){
$w = $item['meta']->getField('File.Width');
$h = $item['meta']->getField('File.Height');
ptln('('.$w.'×'.$h.' '.filesize_h($item['size']).')',6);
ptln($del.'<br />',6);
ptln('<div class="imagemeta">',6);
//build thumbnail
print '<a href="javascript:mediaSelect_attached(\''.$item['id'].'\')">';
if($w>120 || $h>120){
$ratio = $item['meta']->getResizeRatio(120);
$w = floor($w * $ratio);
$h = floor($h * $ratio);
}
$src = ml($item['id'],array('w'=>$w,'h'=>$h));
$p = array();
$p['width'] = $w;
$p['height'] = $h;
$p['alt'] = $item['id'];
$p['class'] = 'thumb';
$att = buildAttributes($p);
print '<img src="'.$src.'" '.$att.' />';
print '</a>';
//read EXIF/IPTC data
$t = $item['meta']->getField('IPTC.Headline');
if($t) print '<b>'.$t.'</b><br />';
$t = $item['meta']->getField(array('IPTC.Caption','EXIF.UserComment',
'EXIF.TIFFImageDescription',
'EXIF.TIFFUserComment'));
if($t) print $t.'<br />';
$t = $item['meta']->getField(array('IPTC.Keywords','IPTC.Category'));
if($t) print '<i>'.$t.'</i><br />';
//add edit button
if($AUTH >= AUTH_UPLOAD && $item['meta']->getField('File.Mime') == 'image/jpeg'){
print '<a href="'.DOKU_BASE.'lib/exe/media.php?edit='.urlencode($item['id']).'">';
print '<img src="'.DOKU_BASE.'lib/images/edit.gif" alt="'.$lang['metaedit'].'" title="'.$lang['metaedit'].'" />';
print '</a>';
}
ptln('</div>',6);
}else{
ptln ('('.filesize_h($item['size']).')',6);
ptln($del,6);
}
ptln('</li>',4);
}
ptln('</ul>',2);
}
tpl/*/layout.css – after /* ————— Media Selection —————– */
.mediaselect_attached {
border:none;
}
lib/scripts/script.js – after function mediaSelect(file)
function mediaSelect_attached(file){
insertAtCarret_attached(window.parent.document.editform.wikitext,'{{'+file+'}}');
window.close();
}
function insertAtCarret_attached(field,value){
//IE support
if (document.selection) {
field.focus();
sel = window.parent.document.selection.createRange();
sel.text = value;
//MOZILLA/NETSCAPE support
}else if (field.selectionStart || field.selectionStart == '0') {
var startPos = field.selectionStart;
var endPos = field.selectionEnd;
var scrollTop = field.scrollTop;
field.value = field.value.substring(0, startPos)
+ value
+ field.value.substring(endPos);
field.focus();
var cPos=startPos+(value.length);
field.selectionStart=cPos;
field.selectionEnd=cPos;
field.scrollTop=scrollTop;
} else {
field.value += "\n"+value;
}
// reposition cursor if possible
if (field.createTextRange) field.caretPos = window.parent.document.selection.createRange().duplicate();
}