18fce80b1SAndreas Gohr<?php 28fce80b1SAndreas Gohr// must be run within Dokuwiki 38fce80b1SAndreas Gohrif(!defined('DOKU_INC')) die(); 48fce80b1SAndreas Gohr 58fce80b1SAndreas Gohrrequire_once DOKU_INC.'inc/parser/renderer.php'; 6e348ef7cSAndreas Gohrrequire_once DOKU_INC.'inc/fulltext.php'; 78fce80b1SAndreas Gohr 88fce80b1SAndreas Gohr/** 98fce80b1SAndreas Gohr * The Renderer 108fce80b1SAndreas Gohr */ 118fce80b1SAndreas Gohrclass renderer_plugin_qc extends Doku_Renderer { 128fce80b1SAndreas Gohr /** 138fce80b1SAndreas Gohr * We store all our data in an array 148fce80b1SAndreas Gohr */ 158fce80b1SAndreas Gohr var $doc = array( 168fce80b1SAndreas Gohr // raw statistics 178fce80b1SAndreas Gohr 'header_count' => array(0,0,0,0,0,0), 188fce80b1SAndreas Gohr 'header_struct' => array(), 198fce80b1SAndreas Gohr 'linebreak' => 0, 208fce80b1SAndreas Gohr 'quote_nest' => 0, 218fce80b1SAndreas Gohr 'quote_count' => 0, 228fce80b1SAndreas Gohr 'fixme' => 0, 238fce80b1SAndreas Gohr 'hr' => 0, 24d723b313SAndreas Gohr 'formatted' => 0, 258fce80b1SAndreas Gohr 264ea373cdSAndreas Gohr 'created' => 0, 274ea373cdSAndreas Gohr 'modified' => 0, 284ea373cdSAndreas Gohr 'changes' => 0, 294ea373cdSAndreas Gohr 'authors' => array(), 304ea373cdSAndreas Gohr 31d723b313SAndreas Gohr 'internal_links'=> 0, 32d723b313SAndreas Gohr 'broken_links' => 0, 33d723b313SAndreas Gohr 'external_links'=> 0, 348d7cf088SAndreas Gohr 'link_lengths' => array(), 35d723b313SAndreas Gohr 364ea373cdSAndreas Gohr 'chars' => 0, 374ea373cdSAndreas Gohr 'words' => 0, 384ea373cdSAndreas Gohr 399068e431SAndreas Gohr 'score' => 0, 409068e431SAndreas Gohr 418fce80b1SAndreas Gohr // calculated error scores 428fce80b1SAndreas Gohr 'err' => array( 438fce80b1SAndreas Gohr 'fixme' => 0, 448fce80b1SAndreas Gohr 'noh1' => 0, 458fce80b1SAndreas Gohr 'manyh1' => 0, 468fce80b1SAndreas Gohr 'headernest' => 0, 478fce80b1SAndreas Gohr 'manyhr' => 0, 488fce80b1SAndreas Gohr 'manybr' => 0, 49d723b313SAndreas Gohr 'longformat' => 0, 504bda998cSAndreas Gohr 'multiformat'=> 0, 518fce80b1SAndreas Gohr ), 528fce80b1SAndreas Gohr ); 538fce80b1SAndreas Gohr 548fce80b1SAndreas Gohr var $quotelevel = 0; 55d723b313SAndreas Gohr var $formatting = 0; 566afc1841Sthesunrise1983 var $tableopen = false; 578fce80b1SAndreas Gohr 584ea373cdSAndreas Gohr function document_start() { 594ea373cdSAndreas Gohr global $ID; 604ea373cdSAndreas Gohr $meta = p_get_metadata($ID); 614ea373cdSAndreas Gohr 624ea373cdSAndreas Gohr // get some dates from meta data 634ea373cdSAndreas Gohr $this->doc['created'] = $meta['date']['created']; 644ea373cdSAndreas Gohr $this->doc['modified'] = $meta['date']['modified']; 654ea373cdSAndreas Gohr 664ea373cdSAndreas Gohr // get author info 675929c83eSMichael Große $changelog = new PageChangelog($ID); 685929c83eSMichael Große $revs = $changelog->getRevisions(0,10000); //FIXME find a good solution for 'get ALL revisions' 694ea373cdSAndreas Gohr array_push($revs,$meta['last_change']['date']); 704ea373cdSAndreas Gohr $this->doc['changes'] = count($revs); 714ea373cdSAndreas Gohr foreach($revs as $rev){ 72*088a1fe7SMichael Grosse $info = $changelog->getRevisionInfo($rev); 734ea373cdSAndreas Gohr if($info['user']){ 744ea373cdSAndreas Gohr $this->doc['authors'][$info['user']] += 1; 754ea373cdSAndreas Gohr }else{ 764ea373cdSAndreas Gohr $this->doc['authors']['*'] += 1; 774ea373cdSAndreas Gohr } 784ea373cdSAndreas Gohr } 794ea373cdSAndreas Gohr 804ea373cdSAndreas Gohr // work on raw text 814ea373cdSAndreas Gohr $text = rawWiki($ID); 824ea373cdSAndreas Gohr $this->doc['chars'] = utf8_strlen($text); 83ad6cda3cSNils Georg Heinrich Reichert $this->doc['words'] = count(array_filter(preg_split('/[^\w\-_]/u',$text))); 844ea373cdSAndreas Gohr } 854ea373cdSAndreas Gohr 864ea373cdSAndreas Gohr 878fce80b1SAndreas Gohr /** 888fce80b1SAndreas Gohr * Here the score is calculated 898fce80b1SAndreas Gohr */ 908fce80b1SAndreas Gohr function document_end() { 91e348ef7cSAndreas Gohr global $ID; 92e348ef7cSAndreas Gohr 93e348ef7cSAndreas Gohr // 2 points for missing backlinks 94e348ef7cSAndreas Gohr if(!count(ft_backlinks($ID))){ 95e348ef7cSAndreas Gohr $this->doc['err']['nobacklink'] += 2; 96e348ef7cSAndreas Gohr } 978fce80b1SAndreas Gohr 988fce80b1SAndreas Gohr // 1 point for each FIXME 998fce80b1SAndreas Gohr $this->doc['err']['fixme'] += $this->doc['fixme']; 1008fce80b1SAndreas Gohr 1018fce80b1SAndreas Gohr // 5 points for missing H1 1028fce80b1SAndreas Gohr if($this->doc['header_count'][1] == 0){ 1038fce80b1SAndreas Gohr $this->doc['err']['noh1'] += 5; 1048fce80b1SAndreas Gohr } 1058fce80b1SAndreas Gohr // 1 point for each H1 too much 1068fce80b1SAndreas Gohr if($this->doc['header_count'][1] > 1){ 1078fce80b1SAndreas Gohr $this->doc['err']['manyh1'] += $this->doc['header'][1]; 1088fce80b1SAndreas Gohr } 1098fce80b1SAndreas Gohr 1108fce80b1SAndreas Gohr // 1 point for each incorrectly nested headline 1118fce80b1SAndreas Gohr $cnt = count($this->doc['header_struct']); 1128fce80b1SAndreas Gohr for($i = 1; $i < $cnt; $i++){ 1138fce80b1SAndreas Gohr if($this->doc['header_struct'][$i] - $this->doc['header_struct'][$i-1] > 1){ 1148fce80b1SAndreas Gohr $this->doc['err']['headernest'] += 1; 1158fce80b1SAndreas Gohr } 1168fce80b1SAndreas Gohr } 1178fce80b1SAndreas Gohr 1188fce80b1SAndreas Gohr // 1/2 points for deeply nested quotations 1198fce80b1SAndreas Gohr if($this->doc['quote_nest'] > 2){ 1208fce80b1SAndreas Gohr $this->doc['err']['deepquote'] += $this->doc['quote_nest']/2; 1218fce80b1SAndreas Gohr } 1228fce80b1SAndreas Gohr 1238fce80b1SAndreas Gohr // FIXME points for many quotes? 1248fce80b1SAndreas Gohr 1258fce80b1SAndreas Gohr // 1/2 points for too many hr 1268fce80b1SAndreas Gohr if($this->doc['hr'] > 2){ 1278fce80b1SAndreas Gohr $this->doc['err']['manyhr'] = ($this->doc['hr'] - 2)/2; 1288fce80b1SAndreas Gohr } 1298fce80b1SAndreas Gohr 1308fce80b1SAndreas Gohr // 1 point for too many line breaks 1318fce80b1SAndreas Gohr if($this->doc['linebreak'] > 2){ 1328fce80b1SAndreas Gohr $this->doc['err']['manybr'] = $this->doc['linebreak'] - 2; 1338fce80b1SAndreas Gohr } 1348fce80b1SAndreas Gohr 1354ea373cdSAndreas Gohr // 1 point for single author only 1366a7733deSthesunrise1983 if(!$this->getConf('single_author_only') && count($this->doc['authors']) == 1){ 1374ea373cdSAndreas Gohr $this->doc['err']['singleauthor'] = 1; 1384ea373cdSAndreas Gohr } 1394ea373cdSAndreas Gohr 140d723b313SAndreas Gohr // 1 point for too small document 141d723b313SAndreas Gohr if($this->doc['chars'] < 150){ 142d723b313SAndreas Gohr $this->doc['err']['toosmall'] = 1; 143d723b313SAndreas Gohr } 144d723b313SAndreas Gohr 145d723b313SAndreas Gohr // 1 point for too large document 146d723b313SAndreas Gohr if($this->doc['chars'] > 100000){ 147d723b313SAndreas Gohr $this->doc['err']['toolarge'] = 1; 148d723b313SAndreas Gohr } 149d723b313SAndreas Gohr 150d723b313SAndreas Gohr // header to text ratio 151d723b313SAndreas Gohr $hc = $this->doc['header_count'][1] + 152d723b313SAndreas Gohr $this->doc['header_count'][2] + 153d723b313SAndreas Gohr $this->doc['header_count'][3] + 154d723b313SAndreas Gohr $this->doc['header_count'][4] + 155d723b313SAndreas Gohr $this->doc['header_count'][5]; 15613abf7ccSAndreas Gohr $hc--; //we expect at least 1 15713abf7ccSAndreas Gohr if($hc > 0){ 158d723b313SAndreas Gohr $hr = $this->doc['chars']/$hc; 159d723b313SAndreas Gohr 160d723b313SAndreas Gohr // 1 point for too many headers 161d723b313SAndreas Gohr if($hr < 200){ 162d723b313SAndreas Gohr $this->doc['err']['manyheaders'] = 1; 163d723b313SAndreas Gohr } 164d723b313SAndreas Gohr 165d723b313SAndreas Gohr // 1 point for too few headers 1661b085f03SAndreas Gohr if($hr > 2000){ 167d723b313SAndreas Gohr $this->doc['err']['fewheaders'] = 1; 168d723b313SAndreas Gohr } 169d723b313SAndreas Gohr } 170d723b313SAndreas Gohr 171d723b313SAndreas Gohr // 1 point when no link at all 172d723b313SAndreas Gohr if(!$this->doc['internal_links']){ 173d723b313SAndreas Gohr $this->doc['err']['nolink'] = 1; 174d723b313SAndreas Gohr } 175d723b313SAndreas Gohr 176d723b313SAndreas Gohr // 0.5 for broken links when too many 177d723b313SAndreas Gohr if($this->doc['broken_links'] > 2){ 178d723b313SAndreas Gohr $this->doc['err']['brokenlink'] = $this->doc['broken_links']*0.5; 179d723b313SAndreas Gohr } 180d723b313SAndreas Gohr 181d723b313SAndreas Gohr // 2 points for lot's of formatting 182d723b313SAndreas Gohr if($this->doc['formatted'] && $this->doc['chars']/$this->doc['formatted'] < 3){ 183d723b313SAndreas Gohr $this->doc['err']['manyformat'] = 2; 184d723b313SAndreas Gohr } 185d723b313SAndreas Gohr 1869068e431SAndreas Gohr // add up all scores 1879068e431SAndreas Gohr foreach($this->doc['err'] as $err => $val) $this->doc['score'] += $val; 1889068e431SAndreas Gohr 1894ea373cdSAndreas Gohr 1908fce80b1SAndreas Gohr //we're done here 1918fce80b1SAndreas Gohr $this->doc = serialize($this->doc); 1928fce80b1SAndreas Gohr } 1938fce80b1SAndreas Gohr 1948fce80b1SAndreas Gohr /** 1958fce80b1SAndreas Gohr * the format we produce 1968fce80b1SAndreas Gohr */ 1978fce80b1SAndreas Gohr function getFormat(){ 1988fce80b1SAndreas Gohr return 'qc'; 1998fce80b1SAndreas Gohr } 2008fce80b1SAndreas Gohr 201d723b313SAndreas Gohr function internallink($id, $name = NULL, $search=NULL,$returnonly=false,$linktype='content') { 202d723b313SAndreas Gohr global $ID; 203d723b313SAndreas Gohr resolve_pageid(getNS($ID),$id,$exists); 204d723b313SAndreas Gohr 2058d7cf088SAndreas Gohr // calculate link width 206d78155a4SAndreas Gohr $a = explode(':',getNS($ID)); 207d78155a4SAndreas Gohr $b = explode(':',getNS($id)); 208d78155a4SAndreas Gohr while(isset($a[0]) && $a[0] == $b[0]){ 2098d7cf088SAndreas Gohr array_shift($a); 2108d7cf088SAndreas Gohr array_shift($b); 2118d7cf088SAndreas Gohr } 212d78155a4SAndreas Gohr $length = count($a)+count($b); 2138d7cf088SAndreas Gohr $this->doc['link_lengths'][] = $length; 2148d7cf088SAndreas Gohr 2150476d180SAndreas Gohr $this->doc['internal_links']++; 2160476d180SAndreas Gohr if(!$exists) $this->doc['broken_links']++; 2170476d180SAndreas Gohr } 2180476d180SAndreas Gohr 2190476d180SAndreas Gohr function externallink($url, $name = NULL) { 2200476d180SAndreas Gohr $this->doc['external_links']++; 221d723b313SAndreas Gohr } 2228fce80b1SAndreas Gohr 2238fce80b1SAndreas Gohr function header($text, $level, $pos){ 2248fce80b1SAndreas Gohr $this->doc['header_count'][$level]++; 2258fce80b1SAndreas Gohr $this->doc['header_struct'][] = $level; 2268fce80b1SAndreas Gohr } 2278fce80b1SAndreas Gohr 2288fce80b1SAndreas Gohr function smiley($smiley) { 2298fce80b1SAndreas Gohr if($smiley == 'FIXME') $this->doc['fixme']++; 2308fce80b1SAndreas Gohr } 2318fce80b1SAndreas Gohr 2328fce80b1SAndreas Gohr function linebreak() { 2336afc1841Sthesunrise1983 if(!$this->tableopen){ 2348fce80b1SAndreas Gohr $this->doc['linebreak']++; 2358fce80b1SAndreas Gohr } 2366afc1841Sthesunrise1983 } 2376afc1841Sthesunrise1983 2386afc1841Sthesunrise1983 function table_open($maxcols = null, $numrows = null, $pos = null){ 2396afc1841Sthesunrise1983 $this->tableopen = true; 2406afc1841Sthesunrise1983 } 2416afc1841Sthesunrise1983 2426afc1841Sthesunrise1983 function table_close($pos = null){ 2436afc1841Sthesunrise1983 $this->tableopen = false; 2446afc1841Sthesunrise1983 } 2458fce80b1SAndreas Gohr 2468fce80b1SAndreas Gohr function hr() { 2478fce80b1SAndreas Gohr $this->doc['hr']++; 2488fce80b1SAndreas Gohr } 2498fce80b1SAndreas Gohr 2508fce80b1SAndreas Gohr function quote_open() { 2518fce80b1SAndreas Gohr $this->doc['quote_count']++; 2528fce80b1SAndreas Gohr $this->quotelevel++; 2538fce80b1SAndreas Gohr $this->doc['quote_nest'] = max($this->quotelevel,$this->doc['quote_nest']); 2548fce80b1SAndreas Gohr } 2558fce80b1SAndreas Gohr 2568fce80b1SAndreas Gohr function quote_close() { 2578fce80b1SAndreas Gohr $this->quotelevel--; 2588fce80b1SAndreas Gohr } 2598fce80b1SAndreas Gohr 260d723b313SAndreas Gohr function strong_open() { 261d723b313SAndreas Gohr $this->formatting++; 262d723b313SAndreas Gohr } 2638fce80b1SAndreas Gohr 264d723b313SAndreas Gohr function strong_close() { 265d723b313SAndreas Gohr $this->formatting--; 266d723b313SAndreas Gohr } 267d723b313SAndreas Gohr 268d723b313SAndreas Gohr function emphasis_open() { 269d723b313SAndreas Gohr $this->formatting++; 270d723b313SAndreas Gohr } 271d723b313SAndreas Gohr 272d723b313SAndreas Gohr function emphasis_close() { 273d723b313SAndreas Gohr $this->formatting--; 274d723b313SAndreas Gohr } 275d723b313SAndreas Gohr 276d723b313SAndreas Gohr function underline_open() { 277d723b313SAndreas Gohr $this->formatting++; 278d723b313SAndreas Gohr } 279d723b313SAndreas Gohr 280d723b313SAndreas Gohr function underline_close() { 281d723b313SAndreas Gohr $this->formatting--; 282d723b313SAndreas Gohr } 283d723b313SAndreas Gohr 284d723b313SAndreas Gohr function cdata($text) { 285d723b313SAndreas Gohr if(!$this->formatting) return; 286d723b313SAndreas Gohr 287d723b313SAndreas Gohr $len = utf8_strlen($text); 288d723b313SAndreas Gohr 289d723b313SAndreas Gohr // 1 point for formattings longer than 500 chars 290d723b313SAndreas Gohr if($len>500) $this->doc['err']['longformat']++; 291d723b313SAndreas Gohr 2924bda998cSAndreas Gohr // 1 point for each multiformatting 2934bda998cSAndreas Gohr if($this->formatting > 1) $this->doc['err']['multiformat'] += 1*($this->formatting - 1); 2944bda998cSAndreas Gohr 295d723b313SAndreas Gohr $this->doc['formatted'] += $len; 296d723b313SAndreas Gohr } 2978fce80b1SAndreas Gohr} 2988fce80b1SAndreas Gohr 2998fce80b1SAndreas Gohr//Setup VIM: ex: et ts=4 enc=utf-8 : 300