1<?php 2// must be run within Dokuwiki 3if(!defined('DOKU_INC')) die(); 4 5// we inherit from the XHTML renderer instead directly of the base renderer 6require_once DOKU_INC.'inc/parser/renderer.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 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 ), 50 ); 51 52 var $quotelevel = 0; 53 var $formatting = 0; 54 55 function document_start() { 56 global $ID; 57 $meta = p_get_metadata($ID); 58 59 // get some dates from meta data 60 $this->doc['created'] = $meta['date']['created']; 61 $this->doc['modified'] = $meta['date']['modified']; 62 63 // get author info 64 $revs = getRevisions($ID,0,0); 65 array_push($revs,$meta['last_change']['date']); 66 $this->doc['changes'] = count($revs); 67 foreach($revs as $rev){ 68 $info = getRevisionInfo($ID, $rev); 69 if($info['user']){ 70 $this->doc['authors'][$info['user']] += 1; 71 }else{ 72 $this->doc['authors']['*'] += 1; 73 } 74 } 75 76 // work on raw text 77 $text = rawWiki($ID); 78 $this->doc['chars'] = utf8_strlen($text); 79 $this->doc['words'] = count(preg_split('/[^\w\-_]/u',$text)); 80 } 81 82 83 /** 84 * Here the score is calculated 85 */ 86 function document_end() { 87 88 // 1 point for each FIXME 89 $this->doc['err']['fixme'] += $this->doc['fixme']; 90 91 // 5 points for missing H1 92 if($this->doc['header_count'][1] == 0){ 93 $this->doc['err']['noh1'] += 5; 94 } 95 // 1 point for each H1 too much 96 if($this->doc['header_count'][1] > 1){ 97 $this->doc['err']['manyh1'] += $this->doc['header'][1]; 98 } 99 100 // 1 point for each incorrectly nested headline 101 $cnt = count($this->doc['header_struct']); 102 for($i = 1; $i < $cnt; $i++){ 103 if($this->doc['header_struct'][$i] - $this->doc['header_struct'][$i-1] > 1){ 104 $this->doc['err']['headernest'] += 1; 105 } 106 } 107 108 // 1/2 points for deeply nested quotations 109 if($this->doc['quote_nest'] > 2){ 110 $this->doc['err']['deepquote'] += $this->doc['quote_nest']/2; 111 } 112 113 // FIXME points for many quotes? 114 115 // 1/2 points for too many hr 116 if($this->doc['hr'] > 2){ 117 $this->doc['err']['manyhr'] = ($this->doc['hr'] - 2)/2; 118 } 119 120 // 1 point for too many line breaks 121 if($this->doc['linebreak'] > 2){ 122 $this->doc['err']['manybr'] = $this->doc['linebreak'] - 2; 123 } 124 125 // 1 point for single author only 126 if(count($this->doc['authors']) == 1){ 127 $this->doc['err']['singleauthor'] = 1; 128 } 129 130 // 1 point for too small document 131 if($this->doc['chars'] < 150){ 132 $this->doc['err']['toosmall'] = 1; 133 } 134 135 // 1 point for too large document 136 if($this->doc['chars'] > 100000){ 137 $this->doc['err']['toolarge'] = 1; 138 } 139 140 // header to text ratio 141 $hc = $this->doc['header_count'][1] + 142 $this->doc['header_count'][2] + 143 $this->doc['header_count'][3] + 144 $this->doc['header_count'][4] + 145 $this->doc['header_count'][5]; 146 if($hc){ 147 $hr = $this->doc['chars']/$hc; 148 149 // 1 point for too many headers 150 if($hr < 200){ 151 $this->doc['err']['manyheaders'] = 1; 152 } 153 154 // 1 point for too few headers 155 if($hr > 2000){ 156 $this->doc['err']['fewheaders'] = 1; 157 } 158 } 159 160 // 1 point when no link at all 161 if(!$this->doc['internal_links']){ 162 $this->doc['err']['nolink'] = 1; 163 } 164 165 // 0.5 for broken links when too many 166 if($this->doc['broken_links'] > 2){ 167 $this->doc['err']['brokenlink'] = $this->doc['broken_links']*0.5; 168 } 169 170 // 2 points for lot's of formatting 171 if($this->doc['formatted'] && $this->doc['chars']/$this->doc['formatted'] < 3){ 172 $this->doc['err']['manyformat'] = 2; 173 } 174 175 // add up all scores 176 foreach($this->doc['err'] as $err => $val) $this->doc['score'] += $val; 177 178 179 //we're done here 180 $this->doc = serialize($this->doc); 181 } 182 183 /** 184 * the format we produce 185 */ 186 function getFormat(){ 187 return 'qc'; 188 } 189 190 function internallink($id, $name = NULL, $search=NULL,$returnonly=false,$linktype='content') { 191 global $ID; 192 resolve_pageid(getNS($ID),$id,$exists); 193 194 $this->doc['internal_link']++; 195 if(!$exists) $this->doc['broken_link']++; 196 } 197 198 function header($text, $level, $pos){ 199 $this->doc['header_count'][$level]++; 200 $this->doc['header_struct'][] = $level; 201 } 202 203 function smiley($smiley) { 204 if($smiley == 'FIXME') $this->doc['fixme']++; 205 } 206 207 function linebreak() { 208 $this->doc['linebreak']++; 209 } 210 211 function hr() { 212 $this->doc['hr']++; 213 } 214 215 function quote_open() { 216 $this->doc['quote_count']++; 217 $this->quotelevel++; 218 $this->doc['quote_nest'] = max($this->quotelevel,$this->doc['quote_nest']); 219 } 220 221 function quote_close() { 222 $this->quotelevel--; 223 } 224 225 function strong_open() { 226 $this->formatting++; 227 } 228 229 function strong_close() { 230 $this->formatting--; 231 } 232 233 function emphasis_open() { 234 $this->formatting++; 235 } 236 237 function emphasis_close() { 238 $this->formatting--; 239 } 240 241 function underline_open() { 242 $this->formatting++; 243 } 244 245 function underline_close() { 246 $this->formatting--; 247 } 248 249 function cdata($text) { 250 if(!$this->formatting) return; 251 252 $len = utf8_strlen($text); 253 254 // 1 point for formattings longer than 500 chars 255 if($len>500) $this->doc['err']['longformat']++; 256 257 $this->doc['formatted'] += $len; 258 } 259} 260 261//Setup VIM: ex: et ts=4 enc=utf-8 : 262