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