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 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() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps 88 { 89 global $ID; 90 91 // 2 points for missing backlinks 92 if (!count(ft_backlinks($ID))) { 93 $this->docArray['err']['nobacklink'] += 2; 94 } 95 96 // 1 point for each FIXME 97 $this->docArray['err']['fixme'] += $this->docArray['fixme']; 98 99 // 5 points for missing H1 100 if ($this->docArray['header_count'][1] == 0) { 101 $this->docArray['err']['noh1'] += 5; 102 } 103 // 1 point for each H1 too much 104 if ($this->docArray['header_count'][1] > 1) { 105 $this->docArray['err']['manyh1'] += $this->docArray['header'][1]; 106 } 107 108 // 1 point for each incorrectly nested headline 109 $cnt = count($this->docArray['header_struct']); 110 for ($i = 1; $i < $cnt; $i++) { 111 if ($this->docArray['header_struct'][$i] - $this->docArray['header_struct'][$i - 1] > 1) { 112 $this->docArray['err']['headernest'] += 1; 113 } 114 } 115 116 // 1/2 points for deeply nested quotations 117 if ($this->docArray['quote_nest'] > 2) { 118 $this->docArray['err']['deepquote'] += $this->docArray['quote_nest'] / 2; 119 } 120 121 // FIXME points for many quotes? 122 123 // 1/2 points for too many hr 124 if ($this->docArray['hr'] > 2) { 125 $this->docArray['err']['manyhr'] = ($this->docArray['hr'] - 2) / 2; 126 } 127 128 // 1 point for too many line breaks 129 if ($this->docArray['linebreak'] > 2) { 130 $this->docArray['err']['manybr'] = $this->docArray['linebreak'] - 2; 131 } 132 133 // 1 point for single author only 134 if (!$this->getConf('single_author_only') && count($this->docArray['authors']) == 1) { 135 $this->docArray['err']['singleauthor'] = 1; 136 } 137 138 // 1 point for too small document 139 if ($this->docArray['chars'] < 150) { 140 $this->docArray['err']['toosmall'] = 1; 141 } 142 143 // 1 point for too large document 144 if ($this->docArray['chars'] > 100000) { 145 $this->docArray['err']['toolarge'] = 1; 146 } 147 148 // header to text ratio 149 $hc = $this->docArray['header_count'][1] + 150 $this->docArray['header_count'][2] + 151 $this->docArray['header_count'][3] + 152 $this->docArray['header_count'][4] + 153 $this->docArray['header_count'][5]; 154 $hc--; //we expect at least 1 155 if ($hc > 0) { 156 $hr = $this->docArray['chars'] / $hc; 157 158 // 1 point for too many headers 159 if ($hr < 200) { 160 $this->docArray['err']['manyheaders'] = 1; 161 } 162 163 // 1 point for too few headers 164 if ($hr > 2000) { 165 $this->docArray['err']['fewheaders'] = 1; 166 } 167 } 168 169 // 1 point when no link at all 170 if (!$this->docArray['internal_links']) { 171 $this->docArray['err']['nolink'] = 1; 172 } 173 174 // 0.5 for broken links when too many 175 if ($this->docArray['broken_links'] > 2) { 176 $this->docArray['err']['brokenlink'] = $this->docArray['broken_links'] * 0.5; 177 } 178 179 // 2 points for lot's of formatting 180 if ($this->docArray['formatted'] && $this->docArray['chars'] / $this->docArray['formatted'] < 3) { 181 $this->docArray['err']['manyformat'] = 2; 182 } 183 184 // add up all scores 185 foreach ($this->docArray['err'] as $err => $val) $this->docArray['score'] += $val; 186 187 188 //we're done here 189 $this->doc = serialize($this->docArray); 190 } 191 192 /** 193 * the format we produce 194 */ 195 public function getFormat() 196 { 197 return 'qc'; 198 } 199 200 public function internallink($id, $name = null, $search = null, $returnonly = false, $linktype = 'content') 201 { 202 global $ID; 203 resolve_pageid(getNS($ID), $id, $exists); 204 205 // calculate link width 206 $a = explode(':', getNS($ID)); 207 $b = explode(':', getNS($id)); 208 while (isset($a[0]) && $a[0] == $b[0]) { 209 array_shift($a); 210 array_shift($b); 211 } 212 $length = count($a) + count($b); 213 $this->docArray['link_lengths'][] = $length; 214 215 $this->docArray['internal_links']++; 216 if (!$exists) $this->docArray['broken_links']++; 217 } 218 219 public function externallink($url, $name = null) 220 { 221 $this->docArray['external_links']++; 222 } 223 224 public function header($text, $level, $pos) 225 { 226 $this->docArray['header_count'][$level]++; 227 $this->docArray['header_struct'][] = $level; 228 } 229 230 public function smiley($smiley) 231 { 232 if ($smiley == 'FIXME') $this->docArray['fixme']++; 233 } 234 235 public function linebreak() 236 { 237 if (!$this->tableopen) { 238 $this->docArray['linebreak']++; 239 } 240 } 241 242 public function table_open($maxcols = null, $numrows = null, $pos = null) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps 243 { 244 $this->tableopen = true; 245 } 246 247 public function table_close($pos = null) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps 248 { 249 $this->tableopen = false; 250 } 251 252 public function hr() 253 { 254 $this->docArray['hr']++; 255 } 256 257 public function quote_open() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps 258 { 259 $this->docArray['quote_count']++; 260 $this->quotelevel++; 261 $this->docArray['quote_nest'] = max($this->quotelevel, $this->docArray['quote_nest']); 262 } 263 264 public function quote_close() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps 265 { 266 $this->quotelevel--; 267 } 268 269 public function strong_open() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps 270 { 271 $this->formatting++; 272 } 273 274 public function strong_close() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps 275 { 276 $this->formatting--; 277 } 278 279 public function emphasis_open() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps 280 { 281 $this->formatting++; 282 } 283 284 public function emphasis_close() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps 285 { 286 $this->formatting--; 287 } 288 289 public function underline_open() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps 290 { 291 $this->formatting++; 292 } 293 294 public function underline_close() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps 295 { 296 $this->formatting--; 297 } 298 299 public function cdata($text) 300 { 301 if (!$this->formatting) return; 302 303 $len = utf8_strlen($text); 304 305 // 1 point for formattings longer than 500 chars 306 if ($len > 500) $this->docArray['err']['longformat']++; 307 308 // 1 point for each multiformatting 309 if ($this->formatting > 1) $this->docArray['err']['multiformat'] += 1 * ($this->formatting - 1); 310 311 $this->docArray['formatted'] += $len; 312 } 313} 314 315//Setup VIM: ex: et ts=4 enc=utf-8 : 316