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