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(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 if($hc){ 155 $hr = $this->doc['chars']/$hc; 156 157 // 1 point for too many headers 158 if($hr < 200){ 159 $this->doc['err']['manyheaders'] = 1; 160 } 161 162 // 1 point for too few headers 163 if($hr > 2000){ 164 $this->doc['err']['fewheaders'] = 1; 165 } 166 } 167 168 // 1 point when no link at all 169 if(!$this->doc['internal_links']){ 170 $this->doc['err']['nolink'] = 1; 171 } 172 173 // 0.5 for broken links when too many 174 if($this->doc['broken_links'] > 2){ 175 $this->doc['err']['brokenlink'] = $this->doc['broken_links']*0.5; 176 } 177 178 // 2 points for lot's of formatting 179 if($this->doc['formatted'] && $this->doc['chars']/$this->doc['formatted'] < 3){ 180 $this->doc['err']['manyformat'] = 2; 181 } 182 183 // add up all scores 184 foreach($this->doc['err'] as $err => $val) $this->doc['score'] += $val; 185 186 187 //we're done here 188 $this->doc = serialize($this->doc); 189 } 190 191 /** 192 * the format we produce 193 */ 194 function getFormat(){ 195 return 'qc'; 196 } 197 198 function internallink($id, $name = NULL, $search=NULL,$returnonly=false,$linktype='content') { 199 global $ID; 200 resolve_pageid(getNS($ID),$id,$exists); 201 202 // calculate link width 203 $a = explode(':',getNS($ID)); 204 $b = explode(':',getNS($id)); 205 while(isset($a[0]) && $a[0] == $b[0]){ 206 array_shift($a); 207 array_shift($b); 208 } 209 $length = count($a)+count($b); 210 $this->doc['link_lengths'][] = $length; 211 212 $this->doc['internal_links']++; 213 if(!$exists) $this->doc['broken_links']++; 214 } 215 216 function externallink($url, $name = NULL) { 217 $this->doc['external_links']++; 218 } 219 220 function header($text, $level, $pos){ 221 $this->doc['header_count'][$level]++; 222 $this->doc['header_struct'][] = $level; 223 } 224 225 function smiley($smiley) { 226 if($smiley == 'FIXME') $this->doc['fixme']++; 227 } 228 229 function linebreak() { 230 $this->doc['linebreak']++; 231 } 232 233 function hr() { 234 $this->doc['hr']++; 235 } 236 237 function quote_open() { 238 $this->doc['quote_count']++; 239 $this->quotelevel++; 240 $this->doc['quote_nest'] = max($this->quotelevel,$this->doc['quote_nest']); 241 } 242 243 function quote_close() { 244 $this->quotelevel--; 245 } 246 247 function strong_open() { 248 $this->formatting++; 249 } 250 251 function strong_close() { 252 $this->formatting--; 253 } 254 255 function emphasis_open() { 256 $this->formatting++; 257 } 258 259 function emphasis_close() { 260 $this->formatting--; 261 } 262 263 function underline_open() { 264 $this->formatting++; 265 } 266 267 function underline_close() { 268 $this->formatting--; 269 } 270 271 function cdata($text) { 272 if(!$this->formatting) return; 273 274 $len = utf8_strlen($text); 275 276 // 1 point for formattings longer than 500 chars 277 if($len>500) $this->doc['err']['longformat']++; 278 279 // 1 point for each multiformatting 280 if($this->formatting > 1) $this->doc['err']['multiformat'] += 1*($this->formatting - 1); 281 282 $this->doc['formatted'] += $len; 283 } 284} 285 286//Setup VIM: ex: et ts=4 enc=utf-8 : 287