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