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