xref: /plugin/qc/renderer.php (revision 088a1fe7bbcab201fe7e8812f24ce9698774b008)
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