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