1<?php 2/** 3 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 4 * @author Martin Schulte <lebowski[at]corvus[dot]uberspace[dot]de> 5 */ 6// must be run within Dokuwiki 7if (!defined('DOKU_INC')) die(); 8 9//constants 10if (!defined('DOKU_LF')) define('DOKU_LF', "\n"); 11if (!defined('DOKU_TAB')) define('DOKU_TAB', "\t"); 12if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC.'lib/plugins/'); 13 14 15 16class helper_plugin_authorlist extends DokuWiki_Plugin 17{ 18 protected $authors = array(); // Contributors-Array (loginname => fullname) 19 // ID for the page, the authors should be diesplayed. Not implemented yet, you can't choose another 20 // page, can only handle the current rendered page. But maybe later. 21 protected $pageID; 22 23 protected $output; 24 25 26 protected $displaystyle; // loginname/fullname or both 27 protected $displayaslist; // List or everything in one line? 28 protected $tooltip; // none, username or fullname. 29 protected $linkto; // can be none, userpage, eMail 30 protected $showheading; // We want a heading? 31 protected $showcreator; // show Creator separat 32 33 // Can't be set using ~~AUTHORS~~ only via adminmenu 34 protected $creatortext; // template for the creatortext (contains %CREATOR% and %DATE% as wildcard) 35 protected $intro; // text before authorlist. 36 protected $userpageid; // Template for the pageID of the userhomepages (contains %USER% as wildcard for the loginname) 37 38 // Some state variables 39 private $cssClass; // classes author, authoruserpage, authoremail are possible depending on the displaystyle. 40 private $openTag; // <li> or <span> 41 private $closeTag; // </li> or </span> 42 private $printempty; // Print everything even if the authorlist is empty 43 private $creatorisauthor; // creator in the authorlist. 44 45 /** 46 * Constructor gets default preferences (calling setOptions(...)) 47 */ 48 public function __construct() { 49 global $INFO; 50 51 // This options can only set using the admin menu. Because you can use html-Syntax for this options. 52 $this->creatortext = $this->getConf('creatortext'); 53 $this->intro = $this->getConf('intro'); 54 $this->userpageid = $this->getConf('userpageid'); 55 $this->linkto = $this->getConf('linkto'); 56 $this->showheading = $this->getConf('showheading'); 57 $this->setOptions($INFO['id'] , null); // set default options 58 } 59 60 61 /** 62 * Set the options. 63 * 64 * @param $pageID String The page the authorlist should be displayed for. (Not implemented yet, only the current rendered page will be handled) 65 * @param $data Array Optionsarray (option => value) 66 */ 67 public function setOptions($pageID, $data){ 68 $this->output=''; 69 $this->pageID = $pageID; 70 $options = array('displayaslist','displaystyle','tooltip','showcreator','printempty', 'creatorisauthor');// possible options 71 foreach($options as $option){ 72 if(isset($data[$option])){ 73 $this->$option = $data[$option]; 74 }else{ 75 $this->$option = $this->getConf($option); 76 } 77 } 78 // find right css-class (author, authoeruserpage, authoremail -> see *.css), sets state variables $this->cssClass 79 $this->findCssClass(); 80 // sets state variables $this->openTag, This->closeTag 81 $this->findOpenAndCloseTags(); 82 } 83 84 /** 85 * Renders the heading 86 */ 87 public function renderHeading(){ 88 // heading? 89 if($this->showheading) $this->output .= "<h2 class='sectionedit1'><a name='authorlist'>".strip_tags($this->getConf('heading'))."</a></h2>".DOKU_LF; 90 return true; 91 } 92 93 94 /** 95 * Starts to render the authorlist: Creatortext, <div class='authorlist'> and maybe <ul class='authorlist'> will be add to $this->output 96 */ 97 public function startList(){ 98 //Show creator separate (before authorlist) 99 if($this->showcreator== "before" ) $this->output .= $this->renderCreator(); 100 // Text before authorslist 101 if(!$this->printempty && empty($this->authors)) return false; 102 $this->output .= $this->intro.DOKU_LF; 103 // open div.authorlist 104 $this->output .= "<div class='authorlist'>".DOKU_LF; 105 if($this->displayaslist) $this->output .= "<ul class='authorlist'>".DOKU_LF; // open <ul> 106 107 return true; 108 } 109 110 /** 111 * Add an author to the $this->authors array 112 * 113 * @param $loginname String Login name of an user. 114 * @param $fullname String (optional) fullname of an user, will be found automatically if empty. 115 */ 116 public function addAuthor($loginname, $fullname=''){ 117 // Get fullname from users.auth 118 if($fullname == '') $fullname = $this-> getFullname($loginname); 119 // add them to the authors-array 120 $this->authors[$loginname] = $fullname; 121 return true; 122 } 123 124 125 126 /** 127 * Get's the authors of an article from the metadata and add them to $this->authors 128 */ 129 public function fetchAuthorsFromMetadata(){ 130 global $INFO; 131 if($this->creatorisauthor || !$this->showcreator){ 132 // Creator is an author (creator not in $INFO['meta']['contributor'] if he/she made no changes 133 list($creator,$creatorfullname) = $this->getCreator(); 134 if(!empty($creator) ) $this->addAuthor($creator,$creatorfullname); 135 } 136 // Authors from metadata 137 if(isset($INFO) && array_key_exists('contributor',$INFO['meta'])) $this->authors = array_merge($INFO['meta']['contributor'],$this->authors); 138 } 139 140 /** 141 * Sort authors in alphabetical order. After calling this function $this->authors ist ordered. 142 */ 143 public function sortAuthors(){ 144 if($this->displaystyle != 'fullname' && $this->displaystyle != 'fullname (loginname)'){ 145 // sort by key 146 ksort($this->authors); 147 }else{ 148 // sort by value 149 asort($this->authors); 150 } 151 } 152 153 /** 154 * Renders all authors and add them to $this->output 155 */ 156 public function renderAllAuthors(){ 157 foreach($this->authors as $loginname => $fullname){ 158 $this->output .= $this->renderOneAuthor($loginname, $fullname); 159 } 160 } 161 162 /** 163 * Finish to render the authorlist: close all open tags. 164 */ 165 public function finishList(){ 166 if($this->printempty || !empty($this->authors)){ 167 // close <ul> 168 if($this->displayaslist) $this->output .= "</ul>".DOKU_LF; 169 // close div 170 $this->output .= "</div>".DOKU_LF; 171 } 172 if($this->showcreator == "below" ) $this->output .= $this->renderCreator(); 173 return true; 174 } 175 176 /** 177 * Returns the current output. Makes sense after calling startlist() renderAllAuthors and finishList() 178 */ 179 public function getOutput(){ 180 return $this->output; 181 } 182 183 /** 184 * Builds the html-code for one author (called for each author by renderAllAuthors()) 185 */ 186 public function renderOneAuthor($loginname, $fullname=''){ 187 $loginname = htmlspecialchars($loginname); 188 $fullname = htmlspecialchars($fullname); 189 // Find text to display on the site. 190 switch($this->displaystyle){ 191 case "fullname": $display = $fullname; break; 192 case "loginname (fullname)": $display = $loginname.($fullname != ''?" (":"").$fullname.($fullname != ''?")":""); break; 193 case "fullname (loginname)": $display = $fullname != ''?"$fullname ($loginname)":$loginname; break; 194 default: $display = $loginname; 195 } 196 $inner = ">"; // $this->openTag has no closing > (so it's possible to add an title="..." 197 // Find title 198 if($this->linkto != 'email'){ 199 switch($this->tooltip){ 200 case "loginname": $inner = "title=\"$loginname\">"; break; 201 case "fullname": $inner = "title=\"$fullname\">"; break; 202 } 203 } 204 global $auth; // if we need to get the eMail-adress. 205 // build a link if necessary 206 switch($this->linkto){ 207 case 'email': $userdata = $auth->getUserData($loginname); $display= $this->email($userdata['mail'], $display, 'authormail'); break; 208 case 'userhomepage': $display = $this->linkToUserhomepage($loginname, $display); break; 209 } 210 // Return the htmlcode for one author. 211 return $this->openTag.$inner.$display.$this->closeTag; 212 } 213 214 /** 215 * Builds the html-code for a link to a userhompage 216 * 217 * @param $loginname String Login name of an user. 218 * @param $display String The Text should be displayed as link. 219 */ 220 private function linkToUserhomepage($loginname, $display){ 221 $userpageid = str_replace("%USER%",$loginname, $this->userpageid); 222 $userpageid = htmlspecialchars($userpageid); 223 if(page_exists($userpageid)) { 224 return '<a href="'.wl($userpageid).'" rel="author" class="wikilink1" title="'.($this->tooltip = 'none'?$userpageid:'').'">'.$display.'</a>'; 225 } else { 226 return '<a href="'.wl($userpageid).'" rel="nofollow" class="wikilink2" title="'.($this->tooltip = 'none'?$userpageid:'').'">'.$display.'</a>'; 227 } 228 } 229 230 /** 231 * Find's the right css-class, depending on on the linkto option. 232 */ 233 private function findCssClass(){ 234 switch($this->linkto){ 235 case "userhomepage": $this->cssClass = "'authoruserpage'"; break; 236 case "email": $this->cssClass = "'authoremail'"; break; 237 default: $this->cssClass = "'author'"; 238 } 239 return true; 240 } 241 242 /** 243 * If displayed as list, we need a <li>-Tag, else we need a <span>-Tag 244 */ 245 private function findOpenAndCloseTags(){ 246 if($this->displayaslist){ 247 $this->openTag = DOKU_TAB."<li class='level1'><div class=".$this->cssClass." "; 248 $this->closeTag = "</div></li>".DOKU_LF; 249 }else{ 250 $this->openTag = DOKU_TAB."<span class=".$this->cssClass." "; 251 $this->closeTag = "</span>".DOKU_LF; 252 } 253 return true; 254 } 255 256 /** 257 * Get the creator from the metadata (https://www.dokuwiki.org/devel:metadata) 258 */ 259 private function getCreator(){ 260 global $INFO; 261 return array($INFO['meta']['user'],$INFO['meta']['creator']); 262 } 263 264 /** 265 * Builds the html-code for the creatorline. 266 */ 267 private function renderCreator($creator = '', $cTime = ''){ 268 $creator = htmlspecialchars($creator); 269 $cTime = htmlspecialchars($cTime); 270 global $INFO; 271 // Get metadata if parameters are empty 272 if($creator == '' && $cTime == ''){ 273 list($creator,$creatorfullname) = $this->getCreator(); 274 $ctime = $INFO['meta']['date']; 275 $ctime = $ctime['created']; 276 } 277 //$creator = "<span class=".$this->cssClass.""; 278 // Handle template for this line 279 if($creator =='') return ""; 280 switch($this->displaystyle){ 281 case "fullname": $creator = $creatorfullname; break; 282 case "loginname (fullname)": $creator = $creator.($creatorfullname != ''?" (":"").$creatorfullname.($creatorfullname != ''?")":""); break; 283 case "fullname (loginname)": $creator = $creatorfullname != ''?"$creatorfullname ($creator)":$creator; break; 284 } 285 global $conf; 286 // build text from template 287 $output = str_replace("%CREATOR%",$creator, $this->creatortext); 288 $output = str_replace("%DATE%",strftime($conf['dformat'],$ctime), $output); 289 return $output.DOKU_LF; 290 } 291 292 /** 293 * Get the fullname for a given login name. 294 */ 295 public function getFullname($loginname){ 296 global $auth; 297 $userdata = $auth->getUserData($loginname); 298 return $userdata['name']; 299 } 300} 301