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