1<?php 2/** 3 * @license GPL 3 (http://www.gnu.org/licenses/gpl.html) 4 * @author Martin Schulte <lebowski[at]corvus[dot]uberspace[dot]de>, 2013 5 */ 6 7//error_reporting (E_ALL | E_STRICT); 8//ini_set ('display_errors', 'On'); 9 10 11// must be run within Dokuwiki 12if (!defined('DOKU_INC')) die(); 13 14if (!defined('DOKU_LF')) define('DOKU_LF', "\n"); 15if (!defined('DOKU_TAB')) define('DOKU_TAB', "\t"); 16if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 17 18require_once(DOKU_PLUGIN.'action.php'); 19 20class action_plugin_owncloud extends DokuWiki_Action_Plugin{ 21 22 // constants 23 const FILEUPDATE = 1; 24 const FILEREMOVE = 2; 25 const NSREMOVE = 3; 26 const WIKISTORAGE = 'wiki'; 27 28 29 /** 30 * Register all hooks 31 */ 32 function register(&$contr) { 33 $contr->register_hook('IO_WIKIPAGE_WRITE','BEFORE',$this,'write'); 34 //$contr->register_hook('PARSER_WIKITEXT_PREPROCESS','BEFORE',$this,'preprocess'); 35 $contr->register_hook('MEDIA_UPLOAD_FINISH','AFTER',$this,'filecache',self::FILEUPDATE); 36 $contr->register_hook('MEDIA_DELETE_FILE','AFTER',$this,'filecache',self::FILEREMOVE); 37 $contr->register_hook('IO_NAMESPACE_DELETED','AFTER',$this,'filecache',self::NSREMOVE); 38 $contr->register_hook('RENDERER_CONTENT_POSTPROCESS','AFTER',$this,'mediaOnThisPage'); 39 $contr->register_hook('TPL_ACT_RENDER','AFTER',$this,'mediaOnThisPageREV'); 40 41 42 43 } 44 45 /** 46 * Returns the path for the correspondig fileID (from table OC_filecache) 47 * Adds a list with all media used on this page to the end of the page 48 * Skips older revisions. 49 */ 50 function mediaOnThisPage(&$event, $param){ 51 global $ID; 52 global $ACT; 53 global $REV; 54 //$event->data[1] .="<h1>Dies ist noch zu sehend</h1>"; 55 if($ACT != 'show') return false; 56 if($REV != 0) return false; // TPL_ACT_RENDER for older revisions 57 if(!page_exists($ID)) return false; 58 $helper = $this->loadHelper('owncloud',false); 59 $list = $helper->getMediaOfThisPage($ID); 60 if(!$list) return false; 61 $event->data[1] .= '<h1 id="headingusedmedia">'.$this->getLang('filesOnThisSide').'</h1>'; 62 $event->data[1] .= $list; 63 64 } 65 66 /** 67 * Returns the path for the correspondig fileID (from table OC_filecache) 68 * Adds a list with all media used on this page to the end of the page 69 * Skips older revisions. 70 */ 71 function mediaOnThisPageREV(&$event, $param){ 72 global $REV; 73 global $ID; 74 if($REV == 0) return false; // see above 75 /* TODO this may not be the real media used on this page. Effectively 76 this are the used media of the current page*/ 77 echo '<h1 id="headingusedmedia">'.$this->getLang('filesOnThisSide').'</h1>'; 78 $helper = $this->loadHelper('owncloud',false); 79 echo $helper->getMediaOfThisPage($ID); 80 } 81 82 /* 83 * Makes sure, that files uploaded or delete using the DokuWiki mediamanager 84 * are updated in the ownCloud database. 85 */ 86 function filecache(&$event, $param){ 87 global $conf; 88 global $INFO; 89 require_once($this->getConf('pathtoowncloud').'/lib/base.php'); 90 $file = str_replace($conf['mediadir'],'/'.self::WIKISTORAGE,$event->data[1]); 91 OC\Files\Filesystem::init($_SERVER['REMOTE_USER'],'/'.$_SERVER['REMOTE_USER'].'/files'); 92 93 switch($param){ 94 case self::FILEUPDATE: $file = str_replace($conf['mediadir'],'/'.self::WIKISTORAGE,$event->data[1]); 95 OC\Files\Cache\Updater::writeUpdate($file); 96 $this->fixDescription(str_replace($conf['mediadir'],'',$event->data[1]),2);// 2, because the medialog entry is already written 97 //OCA\DokuWiki\Storage::dokuwikiUploadFinish($file,$_SERVER['REMOTE_USER'],!$event->data[4]); 98 break; 99 case self::FILEREMOVE: $file = str_replace($conf['mediadir'],'/'.self::WIKISTORAGE,$event->data['path']); 100 OC\Files\Cache\Updater::deleteUpdate($file); 101 break; 102 case self::NSREMOVE: if($event->data[1] == 'media'){ 103 $dir = '/'.self::WIKISTORAGE.'/'.str_replace(':','/',$event->data[0]); 104 OC\Files\Cache\Updater::deleteUpdate($dir); 105 } 106 break; 107 108 109 110 } 111 112 } 113 114 /** 115 * Add fileid or update filepath 116 * 117 * If file exists in the ownCloud database, the fileid will be add to the file parameters, 118 * if fileid exists as parameter, the path will be updated (if necessary) 119 * Changes will be write to disk 120 * 121 */ 122 function write(&$event, $param){ 123 124 $text = $event->data[0][1]; 125 $helper = $this->loadHelper('owncloud',false); 126 global $ID; 127 $helper->dbQuery('DELETE FROM `*PREFIX*dokuwiki_media_use` WHERE `wikipage_hash` = ?', array(md5($ID))); 128 $event->data[0][1] = preg_replace('#\{\{(.+)\}\}#Uise', "'{{'.action_plugin_owncloud::buildLink('\\1',true).'}}'",$text); 129 } 130 131 /** 132 * The same as write, but only for preprocess, e. g. when choose preview. 133 * 134 */ 135 function preprocess(&$event, $param){ 136 $text = $event->data; 137 global $ACT; 138 echo "<h1>$ID</h1>"; 139 $event->data = preg_replace('#\{\{(.+)\}\}#Uise', "'{{'.action_plugin_owncloud::buildLink('\\1',false).'}}'",$text); 140 } 141 142 143 144 /** 145 * Build the link with fileid or update the filepath if fileid is given. 146 * @param string $rawdata the wikitext 147 * 148 */ 149 function buildLink($rawdata, $write = false){ 150 global $ID; 151 $helper = $this->loadHelper('owncloud',false); 152 if(!$helper) return $rawdata; 153 $parts = explode("|",$rawdata); 154 $link = array_shift($parts); 155 // Save alignment 156 $ralign = (bool)preg_match('/^ /',$link); 157 $lalign = (bool)preg_match('/ $/',$link); 158 // delete whitespaces 159 $link = trim($link); 160 if($helper->isExternal($link)) return $rawdata; 161 //split into src and parameters (using the very last questionmark) from /inc/parser/handler.php 162 $pos = strrpos($link,'?'); 163 if($pos != false){ 164 $src = substr($link,0,$pos); 165 $param = substr($link,$pos+1); 166 }else{ 167 $src = $link; 168 $param = ''; 169 } 170 if(preg_match('#fileid=(\d+)?#i',$param,$match)){ 171 ($match[1]) ? $fileid = intval($match[1]) : $fileid = 0; 172 }else{ 173 $fileid = 0; 174 } 175 $desc = implode("|",$parts); 176 // get fileID 177 /*if(count($parts) > 1 ){ // We've a fileid 178 $last = array_pop($parts); 179 $fileid = intval($last); // Last element maybe fileid 180 $desc = implode("|",$parts); // The rest is the description, can contain | 181 if($fileid == 0 ) $desc .= "|".$last; // no fileid, is part of description 182 }else{ 183 $fileid = 0; 184 $desc = array_shift($parts); 185 }*/ 186 // db access 187 188 if($fileid > 0){ // Then find filename from id 189 $path = $helper->getFilenameForID($fileid); 190 if($path != ""){ 191 $src = str_replace('/',':',$path); 192 $notfound = false; 193 }else{ 194 $notfound = true; 195 } 196 }else{ 197 $notfound = true; 198 } 199 // We have no file from id, look for id using source 200 if($notfound){ // Try to find ID from source 201 $oldsrc = $src; 202 resolve_mediaid(getNS($ID),$src, $exists); 203 if($exists){ 204 $fileid = $helper->fileIDForWikiID($src); 205 }else{// Maybe directory 206 $fileid = $helper->fileIDForWikiID($oldsrc); 207 if($fileid != '' && $fileid > 0) $src = $oldsrc; 208 } 209 210 if($fileid == '' || $fileid < 1) return $rawdata; 211 } 212 213 if($write) $this -> mediaUse($fileid,$helper); 214 $param = preg_replace('#fileid=(\d+)?#i',"fileid=$fileid",$param,-1,$count); 215 if($fileid!='' && $fileid > 0 && $count < 1) $param = (($param != "") ? "$param&fileid=$fileid":"fileid=$fileid"); 216 return (($ralign)?" ":"").":".$src.(($param != "") ? "?$param":"").(($lalign)?" ":"")."|".$desc; 217 //return (($ralign)?" ":"").$src.(($param != "") ? "?$param":"").(($lalign)?" ":"")."|".$desc."|".$fileid; 218 } 219 220 /** 221 * Adds a fileid to and the wikiid to table dokuwiki_media_use 222 */ 223 function mediaUse($fileid, &$helper){ 224 global $ID; 225 global $INFO; 226 $heading = (is_array($INFO['meta']['description']['tableofcontents']))?$INFO['meta']['description']['tableofcontents'][0]['title']:''; 227 $helper->dbQuery('INSERT IGNORE INTO `*PREFIX*dokuwiki_media_use` (`fileid`, `wikipage`,`wikipage_hash`,`firstheading`) VALUES (?,?,?,?)', array($fileid, $ID, md5($ID), $heading)); 228 } 229 230 /** 231 * Put the last description/summary as new description (if it is not 'created' or 'deleted') 232 */ 233 function fixDescription($file,$x=1){ 234 global $conf; 235 global $lang; 236 $file = $conf['mediametadir'].'/'.$file.'.changes'; 237 if(file_exists($file)){ 238 $meta = file($file); 239 $desc = ''; 240 $lines = 0; 241 if(!empty($meta)) $lines = count($meta); 242 if($lines >= $x ){ 243 $xLine = $meta[$lines-$x]; 244 $line = explode("\t", $xLine); 245 $desc = (isset($line[5]))?trim($line[5]):''; 246 if($desc == $lang['created'] || $desc == $lang['deleted'] ) $desc=''; 247 // Set desc for the last line 248 $strip = array("\t", "\n"); 249 $lastLine = array_pop($meta); 250 $line = explode("\t", $lastLine); 251 $line[5] = utf8_substr(str_replace($strip, ' ',htmlspecialchars($desc)),0,255); 252 array_push($meta,trim(implode("\t", $line))."\n"); 253 io_saveFile($file,implode("", $meta)); 254 return true; 255 } 256 } 257 return false; 258 } 259} 260