18fce80b1SAndreas Gohr<?php 28fce80b1SAndreas Gohr// must be run within Dokuwiki 38fce80b1SAndreas Gohrif(!defined('DOKU_INC')) die(); 48fce80b1SAndreas Gohr 58fce80b1SAndreas Gohr/** 68fce80b1SAndreas Gohr * The Renderer 78fce80b1SAndreas Gohr */ 88fce80b1SAndreas Gohrclass renderer_plugin_qc extends Doku_Renderer { 98fce80b1SAndreas Gohr /** 108fce80b1SAndreas Gohr * We store all our data in an array 118fce80b1SAndreas Gohr */ 12*7db0beafSAnna Dabrowska public $docArray = array( 138fce80b1SAndreas Gohr // raw statistics 148fce80b1SAndreas Gohr 'header_count' => array(0,0,0,0,0,0), 158fce80b1SAndreas Gohr 'header_struct' => array(), 168fce80b1SAndreas Gohr 'linebreak' => 0, 178fce80b1SAndreas Gohr 'quote_nest' => 0, 188fce80b1SAndreas Gohr 'quote_count' => 0, 198fce80b1SAndreas Gohr 'fixme' => 0, 208fce80b1SAndreas Gohr 'hr' => 0, 21d723b313SAndreas Gohr 'formatted' => 0, 228fce80b1SAndreas Gohr 234ea373cdSAndreas Gohr 'created' => 0, 244ea373cdSAndreas Gohr 'modified' => 0, 254ea373cdSAndreas Gohr 'changes' => 0, 264ea373cdSAndreas Gohr 'authors' => array(), 274ea373cdSAndreas Gohr 28d723b313SAndreas Gohr 'internal_links'=> 0, 29d723b313SAndreas Gohr 'broken_links' => 0, 30d723b313SAndreas Gohr 'external_links'=> 0, 318d7cf088SAndreas Gohr 'link_lengths' => array(), 32d723b313SAndreas Gohr 334ea373cdSAndreas Gohr 'chars' => 0, 344ea373cdSAndreas Gohr 'words' => 0, 354ea373cdSAndreas Gohr 369068e431SAndreas Gohr 'score' => 0, 379068e431SAndreas Gohr 388fce80b1SAndreas Gohr // calculated error scores 398fce80b1SAndreas Gohr 'err' => array( 408fce80b1SAndreas Gohr 'fixme' => 0, 418fce80b1SAndreas Gohr 'noh1' => 0, 428fce80b1SAndreas Gohr 'manyh1' => 0, 438fce80b1SAndreas Gohr 'headernest' => 0, 448fce80b1SAndreas Gohr 'manyhr' => 0, 458fce80b1SAndreas Gohr 'manybr' => 0, 46d723b313SAndreas Gohr 'longformat' => 0, 474bda998cSAndreas Gohr 'multiformat'=> 0, 488fce80b1SAndreas Gohr ), 498fce80b1SAndreas Gohr ); 508fce80b1SAndreas Gohr 51*7db0beafSAnna Dabrowska protected $quotelevel = 0; 52*7db0beafSAnna Dabrowska protected $formatting = 0; 53*7db0beafSAnna Dabrowska protected $tableopen = false; 548fce80b1SAndreas Gohr 55*7db0beafSAnna Dabrowska public function document_start() { 564ea373cdSAndreas Gohr global $ID; 574ea373cdSAndreas Gohr $meta = p_get_metadata($ID); 584ea373cdSAndreas Gohr 594ea373cdSAndreas Gohr // get some dates from meta data 60*7db0beafSAnna Dabrowska $this->docArray['created'] = $meta['date']['created']; 61*7db0beafSAnna Dabrowska $this->docArray['modified'] = $meta['date']['modified']; 624ea373cdSAndreas Gohr 634ea373cdSAndreas Gohr // get author info 645929c83eSMichael Große $changelog = new PageChangelog($ID); 655929c83eSMichael Große $revs = $changelog->getRevisions(0,10000); //FIXME find a good solution for 'get ALL revisions' 664ea373cdSAndreas Gohr array_push($revs,$meta['last_change']['date']); 67*7db0beafSAnna Dabrowska $this->docArray['changes'] = count($revs); 684ea373cdSAndreas Gohr foreach($revs as $rev){ 69088a1fe7SMichael Grosse $info = $changelog->getRevisionInfo($rev); 704ea373cdSAndreas Gohr if($info['user']){ 71*7db0beafSAnna Dabrowska $this->docArray['authors'][$info['user']] += 1; 724ea373cdSAndreas Gohr }else{ 73*7db0beafSAnna Dabrowska $this->docArray['authors']['*'] += 1; 744ea373cdSAndreas Gohr } 754ea373cdSAndreas Gohr } 764ea373cdSAndreas Gohr 774ea373cdSAndreas Gohr // work on raw text 784ea373cdSAndreas Gohr $text = rawWiki($ID); 79*7db0beafSAnna Dabrowska $this->docArray['chars'] = utf8_strlen($text); 80*7db0beafSAnna Dabrowska $this->docArray['words'] = count(array_filter(preg_split('/[^\w\-_]/u',$text))); 814ea373cdSAndreas Gohr } 824ea373cdSAndreas Gohr 834ea373cdSAndreas Gohr 848fce80b1SAndreas Gohr /** 858fce80b1SAndreas Gohr * Here the score is calculated 868fce80b1SAndreas Gohr */ 87*7db0beafSAnna Dabrowska public function document_end() { 88e348ef7cSAndreas Gohr global $ID; 89e348ef7cSAndreas Gohr 90e348ef7cSAndreas Gohr // 2 points for missing backlinks 91e348ef7cSAndreas Gohr if(!count(ft_backlinks($ID))){ 92*7db0beafSAnna Dabrowska $this->docArray['err']['nobacklink'] += 2; 93e348ef7cSAndreas Gohr } 948fce80b1SAndreas Gohr 958fce80b1SAndreas Gohr // 1 point for each FIXME 96*7db0beafSAnna Dabrowska $this->docArray['err']['fixme'] += $this->docArray['fixme']; 978fce80b1SAndreas Gohr 988fce80b1SAndreas Gohr // 5 points for missing H1 99*7db0beafSAnna Dabrowska if($this->docArray['header_count'][1] == 0){ 100*7db0beafSAnna Dabrowska $this->docArray['err']['noh1'] += 5; 1018fce80b1SAndreas Gohr } 1028fce80b1SAndreas Gohr // 1 point for each H1 too much 103*7db0beafSAnna Dabrowska if($this->docArray['header_count'][1] > 1){ 104*7db0beafSAnna Dabrowska $this->docArray['err']['manyh1'] += $this->docArray['header'][1]; 1058fce80b1SAndreas Gohr } 1068fce80b1SAndreas Gohr 1078fce80b1SAndreas Gohr // 1 point for each incorrectly nested headline 108*7db0beafSAnna Dabrowska $cnt = count($this->docArray['header_struct']); 1098fce80b1SAndreas Gohr for($i = 1; $i < $cnt; $i++){ 110*7db0beafSAnna Dabrowska if($this->docArray['header_struct'][$i] - $this->docArray['header_struct'][$i-1] > 1){ 111*7db0beafSAnna Dabrowska $this->docArray['err']['headernest'] += 1; 1128fce80b1SAndreas Gohr } 1138fce80b1SAndreas Gohr } 1148fce80b1SAndreas Gohr 1158fce80b1SAndreas Gohr // 1/2 points for deeply nested quotations 116*7db0beafSAnna Dabrowska if($this->docArray['quote_nest'] > 2){ 117*7db0beafSAnna Dabrowska $this->docArray['err']['deepquote'] += $this->docArray['quote_nest']/2; 1188fce80b1SAndreas Gohr } 1198fce80b1SAndreas Gohr 1208fce80b1SAndreas Gohr // FIXME points for many quotes? 1218fce80b1SAndreas Gohr 1228fce80b1SAndreas Gohr // 1/2 points for too many hr 123*7db0beafSAnna Dabrowska if($this->docArray['hr'] > 2){ 124*7db0beafSAnna Dabrowska $this->docArray['err']['manyhr'] = ($this->docArray['hr'] - 2)/2; 1258fce80b1SAndreas Gohr } 1268fce80b1SAndreas Gohr 1278fce80b1SAndreas Gohr // 1 point for too many line breaks 128*7db0beafSAnna Dabrowska if($this->docArray['linebreak'] > 2){ 129*7db0beafSAnna Dabrowska $this->docArray['err']['manybr'] = $this->docArray['linebreak'] - 2; 1308fce80b1SAndreas Gohr } 1318fce80b1SAndreas Gohr 1324ea373cdSAndreas Gohr // 1 point for single author only 133*7db0beafSAnna Dabrowska if(!$this->getConf('single_author_only') && count($this->docArray['authors']) == 1){ 134*7db0beafSAnna Dabrowska $this->docArray['err']['singleauthor'] = 1; 1354ea373cdSAndreas Gohr } 1364ea373cdSAndreas Gohr 137d723b313SAndreas Gohr // 1 point for too small document 138*7db0beafSAnna Dabrowska if($this->docArray['chars'] < 150){ 139*7db0beafSAnna Dabrowska $this->docArray['err']['toosmall'] = 1; 140d723b313SAndreas Gohr } 141d723b313SAndreas Gohr 142d723b313SAndreas Gohr // 1 point for too large document 143*7db0beafSAnna Dabrowska if($this->docArray['chars'] > 100000){ 144*7db0beafSAnna Dabrowska $this->docArray['err']['toolarge'] = 1; 145d723b313SAndreas Gohr } 146d723b313SAndreas Gohr 147d723b313SAndreas Gohr // header to text ratio 148*7db0beafSAnna Dabrowska $hc = $this->docArray['header_count'][1] + 149*7db0beafSAnna Dabrowska $this->docArray['header_count'][2] + 150*7db0beafSAnna Dabrowska $this->docArray['header_count'][3] + 151*7db0beafSAnna Dabrowska $this->docArray['header_count'][4] + 152*7db0beafSAnna Dabrowska $this->docArray['header_count'][5]; 15313abf7ccSAndreas Gohr $hc--; //we expect at least 1 15413abf7ccSAndreas Gohr if($hc > 0){ 155*7db0beafSAnna Dabrowska $hr = $this->docArray['chars']/$hc; 156d723b313SAndreas Gohr 157d723b313SAndreas Gohr // 1 point for too many headers 158d723b313SAndreas Gohr if($hr < 200){ 159*7db0beafSAnna Dabrowska $this->docArray['err']['manyheaders'] = 1; 160d723b313SAndreas Gohr } 161d723b313SAndreas Gohr 162d723b313SAndreas Gohr // 1 point for too few headers 1631b085f03SAndreas Gohr if($hr > 2000){ 164*7db0beafSAnna Dabrowska $this->docArray['err']['fewheaders'] = 1; 165d723b313SAndreas Gohr } 166d723b313SAndreas Gohr } 167d723b313SAndreas Gohr 168d723b313SAndreas Gohr // 1 point when no link at all 169*7db0beafSAnna Dabrowska if(!$this->docArray['internal_links']){ 170*7db0beafSAnna Dabrowska $this->docArray['err']['nolink'] = 1; 171d723b313SAndreas Gohr } 172d723b313SAndreas Gohr 173d723b313SAndreas Gohr // 0.5 for broken links when too many 174*7db0beafSAnna Dabrowska if($this->docArray['broken_links'] > 2){ 175*7db0beafSAnna Dabrowska $this->docArray['err']['brokenlink'] = $this->docArray['broken_links']*0.5; 176d723b313SAndreas Gohr } 177d723b313SAndreas Gohr 178d723b313SAndreas Gohr // 2 points for lot's of formatting 179*7db0beafSAnna Dabrowska if($this->docArray['formatted'] && $this->docArray['chars']/$this->docArray['formatted'] < 3){ 180*7db0beafSAnna Dabrowska $this->docArray['err']['manyformat'] = 2; 181d723b313SAndreas Gohr } 182d723b313SAndreas Gohr 1839068e431SAndreas Gohr // add up all scores 184*7db0beafSAnna Dabrowska foreach($this->docArray['err'] as $err => $val) $this->docArray['score'] += $val; 1859068e431SAndreas Gohr 1864ea373cdSAndreas Gohr 1878fce80b1SAndreas Gohr //we're done here 188*7db0beafSAnna Dabrowska $this->doc = serialize($this->docArray); 1898fce80b1SAndreas Gohr } 1908fce80b1SAndreas Gohr 1918fce80b1SAndreas Gohr /** 1928fce80b1SAndreas Gohr * the format we produce 1938fce80b1SAndreas Gohr */ 194*7db0beafSAnna Dabrowska public function getFormat(){ 1958fce80b1SAndreas Gohr return 'qc'; 1968fce80b1SAndreas Gohr } 1978fce80b1SAndreas Gohr 198*7db0beafSAnna Dabrowska public function internallink($id, $name = NULL, $search=NULL,$returnonly=false,$linktype='content') { 199d723b313SAndreas Gohr global $ID; 200d723b313SAndreas Gohr resolve_pageid(getNS($ID),$id,$exists); 201d723b313SAndreas Gohr 2028d7cf088SAndreas Gohr // calculate link width 203d78155a4SAndreas Gohr $a = explode(':',getNS($ID)); 204d78155a4SAndreas Gohr $b = explode(':',getNS($id)); 205d78155a4SAndreas Gohr while(isset($a[0]) && $a[0] == $b[0]){ 2068d7cf088SAndreas Gohr array_shift($a); 2078d7cf088SAndreas Gohr array_shift($b); 2088d7cf088SAndreas Gohr } 209d78155a4SAndreas Gohr $length = count($a)+count($b); 210*7db0beafSAnna Dabrowska $this->docArray['link_lengths'][] = $length; 2118d7cf088SAndreas Gohr 212*7db0beafSAnna Dabrowska $this->docArray['internal_links']++; 213*7db0beafSAnna Dabrowska if(!$exists) $this->docArray['broken_links']++; 2140476d180SAndreas Gohr } 2150476d180SAndreas Gohr 216*7db0beafSAnna Dabrowska public function externallink($url, $name = NULL) { 217*7db0beafSAnna Dabrowska $this->docArray['external_links']++; 218d723b313SAndreas Gohr } 2198fce80b1SAndreas Gohr 220*7db0beafSAnna Dabrowska public function header($text, $level, $pos){ 221*7db0beafSAnna Dabrowska $this->docArray['header_count'][$level]++; 222*7db0beafSAnna Dabrowska $this->docArray['header_struct'][] = $level; 2238fce80b1SAndreas Gohr } 2248fce80b1SAndreas Gohr 225*7db0beafSAnna Dabrowska public function smiley($smiley) { 226*7db0beafSAnna Dabrowska if($smiley == 'FIXME') $this->docArray['fixme']++; 2278fce80b1SAndreas Gohr } 2288fce80b1SAndreas Gohr 229*7db0beafSAnna Dabrowska public function linebreak() { 2306afc1841Sthesunrise1983 if(!$this->tableopen){ 231*7db0beafSAnna Dabrowska $this->docArray['linebreak']++; 2328fce80b1SAndreas Gohr } 2336afc1841Sthesunrise1983 } 2346afc1841Sthesunrise1983 235*7db0beafSAnna Dabrowska public function table_open($maxcols = null, $numrows = null, $pos = null){ 2366afc1841Sthesunrise1983 $this->tableopen = true; 2376afc1841Sthesunrise1983 } 2386afc1841Sthesunrise1983 239*7db0beafSAnna Dabrowska public function table_close($pos = null){ 2406afc1841Sthesunrise1983 $this->tableopen = false; 2416afc1841Sthesunrise1983 } 2428fce80b1SAndreas Gohr 243*7db0beafSAnna Dabrowska public function hr() { 244*7db0beafSAnna Dabrowska $this->docArray['hr']++; 2458fce80b1SAndreas Gohr } 2468fce80b1SAndreas Gohr 247*7db0beafSAnna Dabrowska public function quote_open() { 248*7db0beafSAnna Dabrowska $this->docArray['quote_count']++; 2498fce80b1SAndreas Gohr $this->quotelevel++; 250*7db0beafSAnna Dabrowska $this->docArray['quote_nest'] = max($this->quotelevel,$this->docArray['quote_nest']); 2518fce80b1SAndreas Gohr } 2528fce80b1SAndreas Gohr 253*7db0beafSAnna Dabrowska public function quote_close() { 2548fce80b1SAndreas Gohr $this->quotelevel--; 2558fce80b1SAndreas Gohr } 2568fce80b1SAndreas Gohr 257*7db0beafSAnna Dabrowska public function strong_open() { 258d723b313SAndreas Gohr $this->formatting++; 259d723b313SAndreas Gohr } 2608fce80b1SAndreas Gohr 261*7db0beafSAnna Dabrowska public function strong_close() { 262d723b313SAndreas Gohr $this->formatting--; 263d723b313SAndreas Gohr } 264d723b313SAndreas Gohr 265*7db0beafSAnna Dabrowska public function emphasis_open() { 266d723b313SAndreas Gohr $this->formatting++; 267d723b313SAndreas Gohr } 268d723b313SAndreas Gohr 269*7db0beafSAnna Dabrowska public function emphasis_close() { 270d723b313SAndreas Gohr $this->formatting--; 271d723b313SAndreas Gohr } 272d723b313SAndreas Gohr 273*7db0beafSAnna Dabrowska public function underline_open() { 274d723b313SAndreas Gohr $this->formatting++; 275d723b313SAndreas Gohr } 276d723b313SAndreas Gohr 277*7db0beafSAnna Dabrowska public function underline_close() { 278d723b313SAndreas Gohr $this->formatting--; 279d723b313SAndreas Gohr } 280d723b313SAndreas Gohr 281*7db0beafSAnna Dabrowska public function cdata($text) { 282d723b313SAndreas Gohr if(!$this->formatting) return; 283d723b313SAndreas Gohr 284d723b313SAndreas Gohr $len = utf8_strlen($text); 285d723b313SAndreas Gohr 286d723b313SAndreas Gohr // 1 point for formattings longer than 500 chars 287*7db0beafSAnna Dabrowska if($len>500) $this->docArray['err']['longformat']++; 288d723b313SAndreas Gohr 2894bda998cSAndreas Gohr // 1 point for each multiformatting 290*7db0beafSAnna Dabrowska if($this->formatting > 1) $this->docArray['err']['multiformat'] += 1*($this->formatting - 1); 2914bda998cSAndreas Gohr 292*7db0beafSAnna Dabrowska $this->docArray['formatted'] += $len; 293d723b313SAndreas Gohr } 2948fce80b1SAndreas Gohr} 2958fce80b1SAndreas Gohr 2968fce80b1SAndreas Gohr//Setup VIM: ex: et ts=4 enc=utf-8 : 297