1<?php 2// must be run within Dokuwiki 3if(!defined('DOKU_INC')) die(); 4 5require_once DOKU_INC.'inc/parser/renderer.php'; 6require_once DOKU_INC.'inc/fulltext.php'; 7 8/** 9 * The Renderer 10 */ 11class renderer_plugin_qc extends Doku_Renderer { 12 /** 13 * We store all our data in an array 14 */ 15 var $doc = array( 16 // raw statistics 17 'header_count' => array(0,0,0,0,0,0), 18 'header_struct' => array(), 19 'linebreak' => 0, 20 'quote_nest' => 0, 21 'quote_count' => 0, 22 'fixme' => 0, 23 'hr' => 0, 24 'formatted' => 0, 25 26 'created' => 0, 27 'modified' => 0, 28 'changes' => 0, 29 'authors' => array(), 30 31 'internal_links'=> 0, 32 'broken_links' => 0, 33 'external_links'=> 0, 34 'link_lengths' => array(), 35 36 'chars' => 0, 37 'words' => 0, 38 39 'score' => 0, 40 41 // calculated error scores 42 'err' => array( 43 'fixme' => 0, 44 'noh1' => 0, 45 'manyh1' => 0, 46 'headernest' => 0, 47 'manyhr' => 0, 48 'manybr' => 0, 49 'longformat' => 0, 50 'multiformat'=> 0, 51 ), 52 ); 53 54 var $quotelevel = 0; 55 var $formatting = 0; 56 var $tableopen = false; 57 58 function document_start() { 59 global $ID; 60 $meta = p_get_metadata($ID); 61 62 // get some dates from meta data 63 $this->doc['created'] = $meta['date']['created']; 64 $this->doc['modified'] = $meta['date']['modified']; 65 66 // get author info 67 $changelog = new PageChangelog($ID); 68 $revs = $changelog->getRevisions(0,10000); //FIXME find a good solution for 'get ALL revisions' 69 array_push($revs,$meta['last_change']['date']); 70 $this->doc['changes'] = count($revs); 71 foreach($revs as $rev){ 72 $info = $changelog->getRevisionInfo($rev); 73 if($info['user']){ 74 $this->doc['authors'][$info['user']] += 1; 75 }else{ 76 $this->doc['authors']['*'] += 1; 77 } 78 } 79 80 // work on raw text 81 $text = rawWiki($ID); 82 $this->doc['chars'] = utf8_strlen($text); 83 $this->doc['words'] = count(array_filter(preg_split('/[^\w\-_]/u',$text))); 84 } 85 86 87 /** 88 * Here the score is calculated 89 */ 90 function document_end() { 91 global $ID; 92 93 // 2 points for missing backlinks 94 if(!count(ft_backlinks($ID))){ 95 $this->doc['err']['nobacklink'] += 2; 96 } 97 98 // 1 point for each FIXME 99 $this->doc['err']['fixme'] += $this->doc['fixme']; 100 101 // 5 points for missing H1 102 if($this->doc['header_count'][1] == 0){ 103 $this->doc['err']['noh1'] += 5; 104 } 105 // 1 point for each H1 too much 106 if($this->doc['header_count'][1] > 1){ 107 $this->doc['err']['manyh1'] += $this->doc['header'][1]; 108 } 109 110 // 1 point for each incorrectly nested headline 111 $cnt = count($this->doc['header_struct']); 112 for($i = 1; $i < $cnt; $i++){ 113 if($this->doc['header_struct'][$i] - $this->doc['header_struct'][$i-1] > 1){ 114 $this->doc['err']['headernest'] += 1; 115 } 116 } 117 118 // 1/2 points for deeply nested quotations 119 if($this->doc['quote_nest'] > 2){ 120 $this->doc['err']['deepquote'] += $this->doc['quote_nest']/2; 121 } 122 123 // FIXME points for many quotes? 124 125 // 1/2 points for too many hr 126 if($this->doc['hr'] > 2){ 127 $this->doc['err']['manyhr'] = ($this->doc['hr'] - 2)/2; 128 } 129 130 // 1 point for too many line breaks 131 if($this->doc['linebreak'] > 2){ 132 $this->doc['err']['manybr'] = $this->doc['linebreak'] - 2; 133 } 134 135 // 1 point for single author only 136 if(!$this->getConf('single_author_only') && count($this->doc['authors']) == 1){ 137 $this->doc['err']['singleauthor'] = 1; 138 } 139 140 // 1 point for too small document 141 if($this->doc['chars'] < 150){ 142 $this->doc['err']['toosmall'] = 1; 143 } 144 145 // 1 point for too large document 146 if($this->doc['chars'] > 100000){ 147 $this->doc['err']['toolarge'] = 1; 148 } 149 150 // header to text ratio 151 $hc = $this->doc['header_count'][1] + 152 $this->doc['header_count'][2] + 153 $this->doc['header_count'][3] + 154 $this->doc['header_count'][4] + 155 $this->doc['header_count'][5]; 156 $hc--; //we expect at least 1 157 if($hc > 0){ 158 $hr = $this->doc['chars']/$hc; 159 160 // 1 point for too many headers 161 if($hr < 200){ 162 $this->doc['err']['manyheaders'] = 1; 163 } 164 165 // 1 point for too few headers 166 if($hr > 2000){ 167 $this->doc['err']['fewheaders'] = 1; 168 } 169 } 170 171 // 1 point when no link at all 172 if(!$this->doc['internal_links']){ 173 $this->doc['err']['nolink'] = 1; 174 } 175 176 // 0.5 for broken links when too many 177 if($this->doc['broken_links'] > 2){ 178 $this->doc['err']['brokenlink'] = $this->doc['broken_links']*0.5; 179 } 180 181 // 2 points for lot's of formatting 182 if($this->doc['formatted'] && $this->doc['chars']/$this->doc['formatted'] < 3){ 183 $this->doc['err']['manyformat'] = 2; 184 } 185 186 // add up all scores 187 foreach($this->doc['err'] as $err => $val) $this->doc['score'] += $val; 188 189 190 //we're done here 191 $this->doc = serialize($this->doc); 192 } 193 194 /** 195 * the format we produce 196 */ 197 function getFormat(){ 198 return 'qc'; 199 } 200 201 function internallink($id, $name = NULL, $search=NULL,$returnonly=false,$linktype='content') { 202 global $ID; 203 resolve_pageid(getNS($ID),$id,$exists); 204 205 // calculate link width 206 $a = explode(':',getNS($ID)); 207 $b = explode(':',getNS($id)); 208 while(isset($a[0]) && $a[0] == $b[0]){ 209 array_shift($a); 210 array_shift($b); 211 } 212 $length = count($a)+count($b); 213 $this->doc['link_lengths'][] = $length; 214 215 $this->doc['internal_links']++; 216 if(!$exists) $this->doc['broken_links']++; 217 } 218 219 function externallink($url, $name = NULL) { 220 $this->doc['external_links']++; 221 } 222 223 function header($text, $level, $pos){ 224 $this->doc['header_count'][$level]++; 225 $this->doc['header_struct'][] = $level; 226 } 227 228 function smiley($smiley) { 229 if($smiley == 'FIXME') $this->doc['fixme']++; 230 } 231 232 function linebreak() { 233 if(!$this->tableopen){ 234 $this->doc['linebreak']++; 235 } 236 } 237 238 function table_open($maxcols = null, $numrows = null, $pos = null){ 239 $this->tableopen = true; 240 } 241 242 function table_close($pos = null){ 243 $this->tableopen = false; 244 } 245 246 function hr() { 247 $this->doc['hr']++; 248 } 249 250 function quote_open() { 251 $this->doc['quote_count']++; 252 $this->quotelevel++; 253 $this->doc['quote_nest'] = max($this->quotelevel,$this->doc['quote_nest']); 254 } 255 256 function quote_close() { 257 $this->quotelevel--; 258 } 259 260 function strong_open() { 261 $this->formatting++; 262 } 263 264 function strong_close() { 265 $this->formatting--; 266 } 267 268 function emphasis_open() { 269 $this->formatting++; 270 } 271 272 function emphasis_close() { 273 $this->formatting--; 274 } 275 276 function underline_open() { 277 $this->formatting++; 278 } 279 280 function underline_close() { 281 $this->formatting--; 282 } 283 284 function cdata($text) { 285 if(!$this->formatting) return; 286 287 $len = utf8_strlen($text); 288 289 // 1 point for formattings longer than 500 chars 290 if($len>500) $this->doc['err']['longformat']++; 291 292 // 1 point for each multiformatting 293 if($this->formatting > 1) $this->doc['err']['multiformat'] += 1*($this->formatting - 1); 294 295 $this->doc['formatted'] += $len; 296 } 297} 298 299//Setup VIM: ex: et ts=4 enc=utf-8 : 300