xref: /plugin/qc/renderer.php (revision 76bbc49c3993db5faa9303ad0615cbeca3339685)
18fce80b1SAndreas Gohr<?php
2*76bbc49cSAnna Dabrowska
38fce80b1SAndreas Gohr// must be run within Dokuwiki
48fce80b1SAndreas Gohrif (!defined('DOKU_INC')) die();
58fce80b1SAndreas Gohr
68fce80b1SAndreas Gohr/**
78fce80b1SAndreas Gohr * The Renderer
88fce80b1SAndreas Gohr */
9*76bbc49cSAnna Dabrowskaclass renderer_plugin_qc extends Doku_Renderer
10*76bbc49cSAnna Dabrowska{
118fce80b1SAndreas Gohr    /**
128fce80b1SAndreas Gohr     * We store all our data in an array
138fce80b1SAndreas Gohr     */
147db0beafSAnna Dabrowska    public $docArray = array(
158fce80b1SAndreas Gohr        // raw statistics
168fce80b1SAndreas Gohr        'header_count'  => array(0,0,0,0,0,0),
178fce80b1SAndreas Gohr        'header_struct' => array(),
188fce80b1SAndreas Gohr        'linebreak'     => 0,
198fce80b1SAndreas Gohr        'quote_nest'    => 0,
208fce80b1SAndreas Gohr        'quote_count'   => 0,
218fce80b1SAndreas Gohr        'fixme'         => 0,
228fce80b1SAndreas Gohr        'hr'            => 0,
23d723b313SAndreas Gohr        'formatted'     => 0,
248fce80b1SAndreas Gohr
254ea373cdSAndreas Gohr        'created'       => 0,
264ea373cdSAndreas Gohr        'modified'      => 0,
274ea373cdSAndreas Gohr        'changes'       => 0,
284ea373cdSAndreas Gohr        'authors'       => array(),
294ea373cdSAndreas Gohr
30d723b313SAndreas Gohr        'internal_links' => 0,
31d723b313SAndreas Gohr        'broken_links'  => 0,
32d723b313SAndreas Gohr        'external_links' => 0,
338d7cf088SAndreas Gohr        'link_lengths'  => array(),
34d723b313SAndreas Gohr
354ea373cdSAndreas Gohr        'chars'         => 0,
364ea373cdSAndreas Gohr        'words'         => 0,
374ea373cdSAndreas Gohr
389068e431SAndreas Gohr        'score'         => 0,
399068e431SAndreas Gohr
408fce80b1SAndreas Gohr        // calculated error scores
418fce80b1SAndreas Gohr        'err' => array(
428fce80b1SAndreas Gohr            'fixme'      => 0,
438fce80b1SAndreas Gohr            'noh1'       => 0,
448fce80b1SAndreas Gohr            'manyh1'     => 0,
458fce80b1SAndreas Gohr            'headernest' => 0,
468fce80b1SAndreas Gohr            'manyhr'     => 0,
478fce80b1SAndreas Gohr            'manybr'     => 0,
48d723b313SAndreas Gohr            'longformat' => 0,
494bda998cSAndreas Gohr            'multiformat' => 0,
508fce80b1SAndreas Gohr        ),
518fce80b1SAndreas Gohr    );
528fce80b1SAndreas Gohr
537db0beafSAnna Dabrowska    protected $quotelevel = 0;
547db0beafSAnna Dabrowska    protected $formatting = 0;
557db0beafSAnna Dabrowska    protected $tableopen  = false;
568fce80b1SAndreas Gohr
57*76bbc49cSAnna Dabrowska    public function document_start()
58*76bbc49cSAnna Dabrowska    {
594ea373cdSAndreas Gohr        global $ID;
604ea373cdSAndreas Gohr        $meta = p_get_metadata($ID);
614ea373cdSAndreas Gohr
624ea373cdSAndreas Gohr        // get some dates from meta data
637db0beafSAnna Dabrowska        $this->docArray['created']  = $meta['date']['created'];
647db0beafSAnna Dabrowska        $this->docArray['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']);
707db0beafSAnna Dabrowska        $this->docArray['changes'] = count($revs);
714ea373cdSAndreas Gohr        foreach ($revs as $rev) {
72088a1fe7SMichael Grosse            $info = $changelog->getRevisionInfo($rev);
734ea373cdSAndreas Gohr            if ($info['user']) {
747db0beafSAnna Dabrowska                $this->docArray['authors'][$info['user']] += 1;
754ea373cdSAndreas Gohr            } else {
767db0beafSAnna Dabrowska                $this->docArray['authors']['*'] += 1;
774ea373cdSAndreas Gohr            }
784ea373cdSAndreas Gohr        }
794ea373cdSAndreas Gohr
804ea373cdSAndreas Gohr        // work on raw text
814ea373cdSAndreas Gohr        $text = rawWiki($ID);
827db0beafSAnna Dabrowska        $this->docArray['chars'] = utf8_strlen($text);
837db0beafSAnna Dabrowska        $this->docArray['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     */
90*76bbc49cSAnna Dabrowska    public function document_end()
91*76bbc49cSAnna Dabrowska    {
92e348ef7cSAndreas Gohr        global $ID;
93e348ef7cSAndreas Gohr
94e348ef7cSAndreas Gohr        // 2 points for missing backlinks
95e348ef7cSAndreas Gohr        if (!count(ft_backlinks($ID))) {
967db0beafSAnna Dabrowska            $this->docArray['err']['nobacklink'] += 2;
97e348ef7cSAndreas Gohr        }
988fce80b1SAndreas Gohr
998fce80b1SAndreas Gohr        // 1 point for each FIXME
1007db0beafSAnna Dabrowska        $this->docArray['err']['fixme'] += $this->docArray['fixme'];
1018fce80b1SAndreas Gohr
1028fce80b1SAndreas Gohr        // 5 points for missing H1
1037db0beafSAnna Dabrowska        if ($this->docArray['header_count'][1] == 0) {
1047db0beafSAnna Dabrowska            $this->docArray['err']['noh1'] += 5;
1058fce80b1SAndreas Gohr        }
1068fce80b1SAndreas Gohr        // 1 point for each H1 too much
1077db0beafSAnna Dabrowska        if ($this->docArray['header_count'][1] > 1) {
1087db0beafSAnna Dabrowska            $this->docArray['err']['manyh1'] += $this->docArray['header'][1];
1098fce80b1SAndreas Gohr        }
1108fce80b1SAndreas Gohr
1118fce80b1SAndreas Gohr        // 1 point for each incorrectly nested headline
1127db0beafSAnna Dabrowska        $cnt = count($this->docArray['header_struct']);
1138fce80b1SAndreas Gohr        for ($i = 1; $i < $cnt; $i++) {
1147db0beafSAnna Dabrowska            if ($this->docArray['header_struct'][$i] - $this->docArray['header_struct'][$i - 1] > 1) {
1157db0beafSAnna Dabrowska                $this->docArray['err']['headernest'] += 1;
1168fce80b1SAndreas Gohr            }
1178fce80b1SAndreas Gohr        }
1188fce80b1SAndreas Gohr
1198fce80b1SAndreas Gohr        // 1/2 points for deeply nested quotations
1207db0beafSAnna Dabrowska        if ($this->docArray['quote_nest'] > 2) {
1217db0beafSAnna Dabrowska            $this->docArray['err']['deepquote'] += $this->docArray['quote_nest'] / 2;
1228fce80b1SAndreas Gohr        }
1238fce80b1SAndreas Gohr
1248fce80b1SAndreas Gohr        // FIXME points for many quotes?
1258fce80b1SAndreas Gohr
1268fce80b1SAndreas Gohr        // 1/2 points for too many hr
1277db0beafSAnna Dabrowska        if ($this->docArray['hr'] > 2) {
1287db0beafSAnna Dabrowska            $this->docArray['err']['manyhr'] = ($this->docArray['hr'] - 2) / 2;
1298fce80b1SAndreas Gohr        }
1308fce80b1SAndreas Gohr
1318fce80b1SAndreas Gohr        // 1 point for too many line breaks
1327db0beafSAnna Dabrowska        if ($this->docArray['linebreak'] > 2) {
1337db0beafSAnna Dabrowska            $this->docArray['err']['manybr'] = $this->docArray['linebreak'] - 2;
1348fce80b1SAndreas Gohr        }
1358fce80b1SAndreas Gohr
1364ea373cdSAndreas Gohr        // 1 point for single author only
1377db0beafSAnna Dabrowska        if (!$this->getConf('single_author_only') && count($this->docArray['authors']) == 1) {
1387db0beafSAnna Dabrowska            $this->docArray['err']['singleauthor'] = 1;
1394ea373cdSAndreas Gohr        }
1404ea373cdSAndreas Gohr
141d723b313SAndreas Gohr        // 1 point for too small document
1427db0beafSAnna Dabrowska        if ($this->docArray['chars'] < 150) {
1437db0beafSAnna Dabrowska            $this->docArray['err']['toosmall'] = 1;
144d723b313SAndreas Gohr        }
145d723b313SAndreas Gohr
146d723b313SAndreas Gohr        // 1 point for too large document
1477db0beafSAnna Dabrowska        if ($this->docArray['chars'] > 100000) {
1487db0beafSAnna Dabrowska            $this->docArray['err']['toolarge'] = 1;
149d723b313SAndreas Gohr        }
150d723b313SAndreas Gohr
151d723b313SAndreas Gohr        // header to text ratio
1527db0beafSAnna Dabrowska        $hc = $this->docArray['header_count'][1] +
1537db0beafSAnna Dabrowska              $this->docArray['header_count'][2] +
1547db0beafSAnna Dabrowska              $this->docArray['header_count'][3] +
1557db0beafSAnna Dabrowska              $this->docArray['header_count'][4] +
1567db0beafSAnna Dabrowska              $this->docArray['header_count'][5];
15713abf7ccSAndreas Gohr        $hc--; //we expect at least 1
15813abf7ccSAndreas Gohr        if ($hc > 0) {
1597db0beafSAnna Dabrowska            $hr = $this->docArray['chars'] / $hc;
160d723b313SAndreas Gohr
161d723b313SAndreas Gohr            // 1 point for too many headers
162d723b313SAndreas Gohr            if ($hr < 200) {
1637db0beafSAnna Dabrowska                $this->docArray['err']['manyheaders'] = 1;
164d723b313SAndreas Gohr            }
165d723b313SAndreas Gohr
166d723b313SAndreas Gohr            // 1 point for too few headers
1671b085f03SAndreas Gohr            if ($hr > 2000) {
1687db0beafSAnna Dabrowska                $this->docArray['err']['fewheaders'] = 1;
169d723b313SAndreas Gohr            }
170d723b313SAndreas Gohr        }
171d723b313SAndreas Gohr
172d723b313SAndreas Gohr        // 1 point when no link at all
1737db0beafSAnna Dabrowska        if (!$this->docArray['internal_links']) {
1747db0beafSAnna Dabrowska            $this->docArray['err']['nolink'] = 1;
175d723b313SAndreas Gohr        }
176d723b313SAndreas Gohr
177d723b313SAndreas Gohr        // 0.5 for broken links when too many
1787db0beafSAnna Dabrowska        if ($this->docArray['broken_links'] > 2) {
1797db0beafSAnna Dabrowska            $this->docArray['err']['brokenlink'] = $this->docArray['broken_links'] * 0.5;
180d723b313SAndreas Gohr        }
181d723b313SAndreas Gohr
182d723b313SAndreas Gohr        // 2 points for lot's of formatting
1837db0beafSAnna Dabrowska        if ($this->docArray['formatted'] && $this->docArray['chars'] / $this->docArray['formatted'] < 3) {
1847db0beafSAnna Dabrowska            $this->docArray['err']['manyformat'] = 2;
185d723b313SAndreas Gohr        }
186d723b313SAndreas Gohr
1879068e431SAndreas Gohr        // add up all scores
1887db0beafSAnna Dabrowska        foreach ($this->docArray['err'] as $err => $val) $this->docArray['score'] += $val;
1899068e431SAndreas Gohr
1904ea373cdSAndreas Gohr
1918fce80b1SAndreas Gohr        //we're done here
1927db0beafSAnna Dabrowska        $this->doc = serialize($this->docArray);
1938fce80b1SAndreas Gohr    }
1948fce80b1SAndreas Gohr
1958fce80b1SAndreas Gohr    /**
1968fce80b1SAndreas Gohr     * the format we produce
1978fce80b1SAndreas Gohr     */
198*76bbc49cSAnna Dabrowska    public function getFormat()
199*76bbc49cSAnna Dabrowska    {
2008fce80b1SAndreas Gohr        return 'qc';
2018fce80b1SAndreas Gohr    }
2028fce80b1SAndreas Gohr
203*76bbc49cSAnna Dabrowska    public function internallink($id, $name = null, $search = null, $returnonly = false, $linktype = 'content')
204*76bbc49cSAnna Dabrowska    {
205d723b313SAndreas Gohr        global $ID;
206d723b313SAndreas Gohr        resolve_pageid(getNS($ID), $id, $exists);
207d723b313SAndreas Gohr
2088d7cf088SAndreas Gohr        // calculate link width
209d78155a4SAndreas Gohr        $a = explode(':', getNS($ID));
210d78155a4SAndreas Gohr        $b = explode(':', getNS($id));
211d78155a4SAndreas Gohr        while (isset($a[0]) && $a[0] == $b[0]) {
2128d7cf088SAndreas Gohr            array_shift($a);
2138d7cf088SAndreas Gohr            array_shift($b);
2148d7cf088SAndreas Gohr        }
215d78155a4SAndreas Gohr        $length = count($a) + count($b);
2167db0beafSAnna Dabrowska        $this->docArray['link_lengths'][] = $length;
2178d7cf088SAndreas Gohr
2187db0beafSAnna Dabrowska        $this->docArray['internal_links']++;
2197db0beafSAnna Dabrowska        if (!$exists) $this->docArray['broken_links']++;
2200476d180SAndreas Gohr    }
2210476d180SAndreas Gohr
222*76bbc49cSAnna Dabrowska    public function externallink($url, $name = null)
223*76bbc49cSAnna Dabrowska    {
2247db0beafSAnna Dabrowska        $this->docArray['external_links']++;
225d723b313SAndreas Gohr    }
2268fce80b1SAndreas Gohr
227*76bbc49cSAnna Dabrowska    public function header($text, $level, $pos)
228*76bbc49cSAnna Dabrowska    {
2297db0beafSAnna Dabrowska        $this->docArray['header_count'][$level]++;
2307db0beafSAnna Dabrowska        $this->docArray['header_struct'][] = $level;
2318fce80b1SAndreas Gohr    }
2328fce80b1SAndreas Gohr
233*76bbc49cSAnna Dabrowska    public function smiley($smiley)
234*76bbc49cSAnna Dabrowska    {
2357db0beafSAnna Dabrowska        if ($smiley == 'FIXME') $this->docArray['fixme']++;
2368fce80b1SAndreas Gohr    }
2378fce80b1SAndreas Gohr
238*76bbc49cSAnna Dabrowska    public function linebreak()
239*76bbc49cSAnna Dabrowska    {
2406afc1841Sthesunrise1983        if (!$this->tableopen) {
2417db0beafSAnna Dabrowska            $this->docArray['linebreak']++;
2428fce80b1SAndreas Gohr        }
2436afc1841Sthesunrise1983    }
2446afc1841Sthesunrise1983
245*76bbc49cSAnna Dabrowska    public function table_open($maxcols = null, $numrows = null, $pos = null)
246*76bbc49cSAnna Dabrowska    {
2476afc1841Sthesunrise1983        $this->tableopen = true;
2486afc1841Sthesunrise1983    }
2496afc1841Sthesunrise1983
250*76bbc49cSAnna Dabrowska    public function table_close($pos = null)
251*76bbc49cSAnna Dabrowska    {
2526afc1841Sthesunrise1983        $this->tableopen = false;
2536afc1841Sthesunrise1983    }
2548fce80b1SAndreas Gohr
255*76bbc49cSAnna Dabrowska    public function hr()
256*76bbc49cSAnna Dabrowska    {
2577db0beafSAnna Dabrowska        $this->docArray['hr']++;
2588fce80b1SAndreas Gohr    }
2598fce80b1SAndreas Gohr
260*76bbc49cSAnna Dabrowska    public function quote_open()
261*76bbc49cSAnna Dabrowska    {
2627db0beafSAnna Dabrowska        $this->docArray['quote_count']++;
2638fce80b1SAndreas Gohr        $this->quotelevel++;
2647db0beafSAnna Dabrowska        $this->docArray['quote_nest'] = max($this->quotelevel, $this->docArray['quote_nest']);
2658fce80b1SAndreas Gohr    }
2668fce80b1SAndreas Gohr
267*76bbc49cSAnna Dabrowska    public function quote_close()
268*76bbc49cSAnna Dabrowska    {
2698fce80b1SAndreas Gohr        $this->quotelevel--;
2708fce80b1SAndreas Gohr    }
2718fce80b1SAndreas Gohr
272*76bbc49cSAnna Dabrowska    public function strong_open()
273*76bbc49cSAnna Dabrowska    {
274d723b313SAndreas Gohr        $this->formatting++;
275d723b313SAndreas Gohr    }
2768fce80b1SAndreas Gohr
277*76bbc49cSAnna Dabrowska    public function strong_close()
278*76bbc49cSAnna Dabrowska    {
279d723b313SAndreas Gohr        $this->formatting--;
280d723b313SAndreas Gohr    }
281d723b313SAndreas Gohr
282*76bbc49cSAnna Dabrowska    public function emphasis_open()
283*76bbc49cSAnna Dabrowska    {
284d723b313SAndreas Gohr        $this->formatting++;
285d723b313SAndreas Gohr    }
286d723b313SAndreas Gohr
287*76bbc49cSAnna Dabrowska    public function emphasis_close()
288*76bbc49cSAnna Dabrowska    {
289d723b313SAndreas Gohr        $this->formatting--;
290d723b313SAndreas Gohr    }
291d723b313SAndreas Gohr
292*76bbc49cSAnna Dabrowska    public function underline_open()
293*76bbc49cSAnna Dabrowska    {
294d723b313SAndreas Gohr        $this->formatting++;
295d723b313SAndreas Gohr    }
296d723b313SAndreas Gohr
297*76bbc49cSAnna Dabrowska    public function underline_close()
298*76bbc49cSAnna Dabrowska    {
299d723b313SAndreas Gohr        $this->formatting--;
300d723b313SAndreas Gohr    }
301d723b313SAndreas Gohr
302*76bbc49cSAnna Dabrowska    public function cdata($text)
303*76bbc49cSAnna Dabrowska    {
304d723b313SAndreas Gohr        if (!$this->formatting) return;
305d723b313SAndreas Gohr
306d723b313SAndreas Gohr        $len = utf8_strlen($text);
307d723b313SAndreas Gohr
308d723b313SAndreas Gohr        // 1 point for formattings longer than 500 chars
3097db0beafSAnna Dabrowska        if ($len > 500) $this->docArray['err']['longformat']++;
310d723b313SAndreas Gohr
3114bda998cSAndreas Gohr        // 1 point for each multiformatting
3127db0beafSAnna Dabrowska        if ($this->formatting > 1) $this->docArray['err']['multiformat'] += 1 * ($this->formatting - 1);
3134bda998cSAndreas Gohr
3147db0beafSAnna Dabrowska        $this->docArray['formatted'] += $len;
315d723b313SAndreas Gohr    }
3168fce80b1SAndreas Gohr}
3178fce80b1SAndreas Gohr
3188fce80b1SAndreas Gohr//Setup VIM: ex: et ts=4 enc=utf-8 :
319