1<?php 2 3 4/** 5 * Linkback helper plugin 6 * 7 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 8 * @author Gina Haeussge <osd@foosel.net> 9 */ 10 11class helper_plugin_linkback extends DokuWiki_Plugin { 12 13 function getMethods() { 14 $result = array (); 15 $result[] = array ( 16 'name' => 'th', 17 'desc' => 'returns the header of the linkback column for pagelist', 18 'return' => array ( 19 'header' => 'string' 20 ), 21 ); 22 $result[] = array ( 23 'name' => 'td', 24 'desc' => 'returns the link to the linkback section with number of comments', 25 'params' => array ( 26 'id' => 'string', 27 'number of linkbacks (optional)' => 'integer' 28 ), 29 'return' => array ( 30 'link' => 'string' 31 ), 32 ); 33 $result[] = array ( 34 'name' => 'getLinkbacks', 35 'desc' => 'returns recently added linkbacks individually', 36 'params' => array ( 37 'namespace' => 'string', 38 'number (optional)' => 'integer' 39 ), 40 'return' => array ( 41 'pages' => 'array' 42 ), 43 ); 44 return $result; 45 } 46 47 /** 48 * Returns the header of the linkback column for the pagelist 49 */ 50 function th() { 51 return $this->getLang('linkbacks'); 52 } 53 54 /** 55 * Returns the link to the linkback section with number of comments 56 */ 57 function td($ID, $number = NULL) { 58 $section = '#linkback__section'; 59 60 if (!isset ($number)) { 61 $lfile = metaFN($ID, '.linkbacks'); 62 $linkbacks = unserialize(io_readFile($lfile, false)); 63 64 if ($linkbacks){ 65 $number = $linkbacks['number']; 66 if (!$linkbacks['display']) { 67 return ''; 68 } 69 } else { 70 return ''; 71 } 72 } 73 74 if ($number == 0) { 75 $linkback = '0 ' . $this->getLang('linkback_plural'); 76 } elseif ($number == 1) { 77 $linkback = '1 ' . $this->getLang('linkback_singular'); 78 } else { 79 $linkback = $number . ' ' . $this->getLang('linkback_plural'); 80 } 81 82 return '<a href="' . wl($ID) . $section . '" class="wikilink1" title="' . $ID . $section . '">' . 83 $linkback . '</a>'; 84 85 } 86 87 /** 88 * Returns recently added linkbacks individually 89 */ 90 function getLinkbacks($ns, $num = NULL) { 91 global $conf; 92 93 $first = $_REQUEST['first']; 94 if (!is_numeric($first)) { 95 $first = 0; 96 } 97 98 if ((!$num) || (!is_numeric($num))) { 99 $num = $conf['recent']; 100 } 101 102 $result = array (); 103 $count = 0; 104 105 if (!@ file_exists($conf['metadir'] . '/_linkbacks.changes')) { 106 return $result; 107 } 108 109 // read all recent changes. (kept short) 110 $lines = file($conf['metadir'] . '/_linkbacks.changes'); 111 112 // handle lines 113 for ($i = count($lines) - 1; $i >= 0; $i--) { 114 $rec = $this->_handleRecentLinkback($lines[$i], $ns); 115 if ($rec !== false) { 116 if (-- $first >= 0) { 117 continue; 118 } // skip first entries 119 $result[$rec['date']] = $rec; 120 $count++; 121 // break when we have enough entries 122 if ($count >= $num) { 123 break; 124 } 125 } 126 } 127 128 // finally sort by time of last comment 129 krsort($result); 130 131 return $result; 132 } 133 134 /** 135 * Internal function used by $this->getLinkbacks() 136 * 137 * don't call directly 138 * 139 * @see getRecentComments() 140 * @author Andreas Gohr <andi@splitbrain.org> 141 * @author Ben Coburn <btcoburn@silicodon.net> 142 * @author Esther Brunner <wikidesign@gmail.com> 143 * @author Gina Haeussge <osd@foosel.net> 144 */ 145 function _handleRecentLinkback($line, $ns) { 146 static $seen = array (); //caches seen pages and skip them 147 if (empty ($line)) { 148 return false; //skip empty lines 149 } 150 151 // split the line into parts 152 $recent = parseChangelogLine($line); 153 if ($recent === false) { 154 return false; 155 } 156 157 $lid = $recent['extra']; 158 $fulllid = $recent['id'] . '#' . $recent['extra']; 159 160 // skip seen ones 161 if (isset ($seen[$fulllid])) { 162 return false; 163 } 164 165 // skip 'show comment' log entries 166 if ($recent['type'] === 'sc') { 167 return false; 168 } 169 170 // remember in seen to skip additional sights 171 $seen[$fulllid] = 1; 172 173 // check if it's a hidden page or comment 174 if (isHiddenPage($recent['id'])) { 175 return false; 176 } 177 if ($recent['type'] === 'hl') { 178 return false; 179 } 180 181 // filter namespace or id 182 if (($ns) && (strpos($recent['id'] . ':', $ns . ':') !== 0)) { 183 return false; 184 } 185 186 // check ACL 187 $recent['perm'] = auth_quickaclcheck($recent['id']); 188 if ($recent['perm'] < AUTH_READ) { 189 return false; 190 } 191 192 // check existance 193 $recent['file'] = wikiFN($recent['id']); 194 $recent['exists'] = @ file_exists($recent['file']); 195 if (!$recent['exists']) { 196 return false; 197 } 198 if ($recent['type'] === 'dc') { 199 return false; 200 } 201 202 // get linkback meta file name 203 $data = unserialize(io_readFile(metaFN($recent['id'], '.linkbacks'), false)); 204 205 // check if discussion is turned off 206 if (!$data['display']) { 207 return false; 208 } 209 210 // okay, then add some additional info 211 $recent['name'] = $data['receivedpings'][$lid]['url']; 212 $recent['desc'] = $data['receivedpings'][$lid]['excerpt']; 213 214 return $recent; 215 } 216 217} 218