xref: /plugin/qc/renderer.php (revision 293182bb8df16cb86ab290c9f83a9605de753704)
18fce80b1SAndreas Gohr<?php
276bbc49cSAnna Dabrowska
38fce80b1SAndreas Gohr/**
48fce80b1SAndreas Gohr * The Renderer
58fce80b1SAndreas Gohr */
676bbc49cSAnna Dabrowskaclass renderer_plugin_qc extends Doku_Renderer
776bbc49cSAnna Dabrowska{
88fce80b1SAndreas Gohr    /**
98fce80b1SAndreas Gohr     * We store all our data in an array
108fce80b1SAndreas Gohr     */
117db0beafSAnna Dabrowska    public $docArray = array(
128fce80b1SAndreas Gohr        // raw statistics
138fce80b1SAndreas Gohr        'header_count'  => array(0,0,0,0,0,0),
148fce80b1SAndreas Gohr        'header_struct' => array(),
158fce80b1SAndreas Gohr        'linebreak'     => 0,
168fce80b1SAndreas Gohr        'quote_nest'    => 0,
178fce80b1SAndreas Gohr        'quote_count'   => 0,
188fce80b1SAndreas Gohr        'fixme'         => 0,
198fce80b1SAndreas Gohr        'hr'            => 0,
20d723b313SAndreas Gohr        'formatted'     => 0,
218fce80b1SAndreas Gohr
224ea373cdSAndreas Gohr        'created'       => 0,
234ea373cdSAndreas Gohr        'modified'      => 0,
244ea373cdSAndreas Gohr        'changes'       => 0,
254ea373cdSAndreas Gohr        'authors'       => array(),
264ea373cdSAndreas Gohr
27d723b313SAndreas Gohr        'internal_links' => 0,
28d723b313SAndreas Gohr        'broken_links'  => 0,
29d723b313SAndreas Gohr        'external_links' => 0,
308d7cf088SAndreas Gohr        'link_lengths'  => array(),
31d723b313SAndreas Gohr
324ea373cdSAndreas Gohr        'chars'         => 0,
334ea373cdSAndreas Gohr        'words'         => 0,
344ea373cdSAndreas Gohr
359068e431SAndreas Gohr        'score'         => 0,
369068e431SAndreas Gohr
378fce80b1SAndreas Gohr        // calculated error scores
388fce80b1SAndreas Gohr        'err' => array(
398fce80b1SAndreas Gohr            'fixme'      => 0,
408fce80b1SAndreas Gohr            'noh1'       => 0,
418fce80b1SAndreas Gohr            'manyh1'     => 0,
428fce80b1SAndreas Gohr            'headernest' => 0,
438fce80b1SAndreas Gohr            'manyhr'     => 0,
448fce80b1SAndreas Gohr            'manybr'     => 0,
45d723b313SAndreas Gohr            'longformat' => 0,
464bda998cSAndreas Gohr            'multiformat' => 0,
478fce80b1SAndreas Gohr        ),
488fce80b1SAndreas Gohr    );
498fce80b1SAndreas Gohr
507db0beafSAnna Dabrowska    protected $quotelevel = 0;
517db0beafSAnna Dabrowska    protected $formatting = 0;
527db0beafSAnna Dabrowska    protected $tableopen  = false;
538fce80b1SAndreas Gohr
54*293182bbSAnna Dabrowska    public function document_start() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
5576bbc49cSAnna Dabrowska    {
564ea373cdSAndreas Gohr        global $ID;
574ea373cdSAndreas Gohr        $meta = p_get_metadata($ID);
584ea373cdSAndreas Gohr
594ea373cdSAndreas Gohr        // get some dates from meta data
607db0beafSAnna Dabrowska        $this->docArray['created']  = $meta['date']['created'];
617db0beafSAnna 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']);
677db0beafSAnna Dabrowska        $this->docArray['changes'] = count($revs);
684ea373cdSAndreas Gohr        foreach ($revs as $rev) {
69088a1fe7SMichael Grosse            $info = $changelog->getRevisionInfo($rev);
704ea373cdSAndreas Gohr            if ($info['user']) {
717db0beafSAnna Dabrowska                $this->docArray['authors'][$info['user']] += 1;
724ea373cdSAndreas Gohr            } else {
737db0beafSAnna Dabrowska                $this->docArray['authors']['*'] += 1;
744ea373cdSAndreas Gohr            }
754ea373cdSAndreas Gohr        }
764ea373cdSAndreas Gohr
774ea373cdSAndreas Gohr        // work on raw text
784ea373cdSAndreas Gohr        $text = rawWiki($ID);
797db0beafSAnna Dabrowska        $this->docArray['chars'] = utf8_strlen($text);
807db0beafSAnna 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*293182bbSAnna Dabrowska    public function document_end() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
8876bbc49cSAnna Dabrowska    {
89e348ef7cSAndreas Gohr        global $ID;
90e348ef7cSAndreas Gohr
91e348ef7cSAndreas Gohr        // 2 points for missing backlinks
92e348ef7cSAndreas Gohr        if (!count(ft_backlinks($ID))) {
937db0beafSAnna Dabrowska            $this->docArray['err']['nobacklink'] += 2;
94e348ef7cSAndreas Gohr        }
958fce80b1SAndreas Gohr
968fce80b1SAndreas Gohr        // 1 point for each FIXME
977db0beafSAnna Dabrowska        $this->docArray['err']['fixme'] += $this->docArray['fixme'];
988fce80b1SAndreas Gohr
998fce80b1SAndreas Gohr        // 5 points for missing H1
1007db0beafSAnna Dabrowska        if ($this->docArray['header_count'][1] == 0) {
1017db0beafSAnna Dabrowska            $this->docArray['err']['noh1'] += 5;
1028fce80b1SAndreas Gohr        }
1038fce80b1SAndreas Gohr        // 1 point for each H1 too much
1047db0beafSAnna Dabrowska        if ($this->docArray['header_count'][1] > 1) {
1057db0beafSAnna Dabrowska            $this->docArray['err']['manyh1'] += $this->docArray['header'][1];
1068fce80b1SAndreas Gohr        }
1078fce80b1SAndreas Gohr
1088fce80b1SAndreas Gohr        // 1 point for each incorrectly nested headline
1097db0beafSAnna Dabrowska        $cnt = count($this->docArray['header_struct']);
1108fce80b1SAndreas Gohr        for ($i = 1; $i < $cnt; $i++) {
1117db0beafSAnna Dabrowska            if ($this->docArray['header_struct'][$i] - $this->docArray['header_struct'][$i - 1] > 1) {
1127db0beafSAnna Dabrowska                $this->docArray['err']['headernest'] += 1;
1138fce80b1SAndreas Gohr            }
1148fce80b1SAndreas Gohr        }
1158fce80b1SAndreas Gohr
1168fce80b1SAndreas Gohr        // 1/2 points for deeply nested quotations
1177db0beafSAnna Dabrowska        if ($this->docArray['quote_nest'] > 2) {
1187db0beafSAnna Dabrowska            $this->docArray['err']['deepquote'] += $this->docArray['quote_nest'] / 2;
1198fce80b1SAndreas Gohr        }
1208fce80b1SAndreas Gohr
1218fce80b1SAndreas Gohr        // FIXME points for many quotes?
1228fce80b1SAndreas Gohr
1238fce80b1SAndreas Gohr        // 1/2 points for too many hr
1247db0beafSAnna Dabrowska        if ($this->docArray['hr'] > 2) {
1257db0beafSAnna Dabrowska            $this->docArray['err']['manyhr'] = ($this->docArray['hr'] - 2) / 2;
1268fce80b1SAndreas Gohr        }
1278fce80b1SAndreas Gohr
1288fce80b1SAndreas Gohr        // 1 point for too many line breaks
1297db0beafSAnna Dabrowska        if ($this->docArray['linebreak'] > 2) {
1307db0beafSAnna Dabrowska            $this->docArray['err']['manybr'] = $this->docArray['linebreak'] - 2;
1318fce80b1SAndreas Gohr        }
1328fce80b1SAndreas Gohr
1334ea373cdSAndreas Gohr        // 1 point for single author only
1347db0beafSAnna Dabrowska        if (!$this->getConf('single_author_only') && count($this->docArray['authors']) == 1) {
1357db0beafSAnna Dabrowska            $this->docArray['err']['singleauthor'] = 1;
1364ea373cdSAndreas Gohr        }
1374ea373cdSAndreas Gohr
138d723b313SAndreas Gohr        // 1 point for too small document
1397db0beafSAnna Dabrowska        if ($this->docArray['chars'] < 150) {
1407db0beafSAnna Dabrowska            $this->docArray['err']['toosmall'] = 1;
141d723b313SAndreas Gohr        }
142d723b313SAndreas Gohr
143d723b313SAndreas Gohr        // 1 point for too large document
1447db0beafSAnna Dabrowska        if ($this->docArray['chars'] > 100000) {
1457db0beafSAnna Dabrowska            $this->docArray['err']['toolarge'] = 1;
146d723b313SAndreas Gohr        }
147d723b313SAndreas Gohr
148d723b313SAndreas Gohr        // header to text ratio
1497db0beafSAnna Dabrowska        $hc = $this->docArray['header_count'][1] +
1507db0beafSAnna Dabrowska              $this->docArray['header_count'][2] +
1517db0beafSAnna Dabrowska              $this->docArray['header_count'][3] +
1527db0beafSAnna Dabrowska              $this->docArray['header_count'][4] +
1537db0beafSAnna Dabrowska              $this->docArray['header_count'][5];
15413abf7ccSAndreas Gohr        $hc--; //we expect at least 1
15513abf7ccSAndreas Gohr        if ($hc > 0) {
1567db0beafSAnna Dabrowska            $hr = $this->docArray['chars'] / $hc;
157d723b313SAndreas Gohr
158d723b313SAndreas Gohr            // 1 point for too many headers
159d723b313SAndreas Gohr            if ($hr < 200) {
1607db0beafSAnna Dabrowska                $this->docArray['err']['manyheaders'] = 1;
161d723b313SAndreas Gohr            }
162d723b313SAndreas Gohr
163d723b313SAndreas Gohr            // 1 point for too few headers
1641b085f03SAndreas Gohr            if ($hr > 2000) {
1657db0beafSAnna Dabrowska                $this->docArray['err']['fewheaders'] = 1;
166d723b313SAndreas Gohr            }
167d723b313SAndreas Gohr        }
168d723b313SAndreas Gohr
169d723b313SAndreas Gohr        // 1 point when no link at all
1707db0beafSAnna Dabrowska        if (!$this->docArray['internal_links']) {
1717db0beafSAnna Dabrowska            $this->docArray['err']['nolink'] = 1;
172d723b313SAndreas Gohr        }
173d723b313SAndreas Gohr
174d723b313SAndreas Gohr        // 0.5 for broken links when too many
1757db0beafSAnna Dabrowska        if ($this->docArray['broken_links'] > 2) {
1767db0beafSAnna Dabrowska            $this->docArray['err']['brokenlink'] = $this->docArray['broken_links'] * 0.5;
177d723b313SAndreas Gohr        }
178d723b313SAndreas Gohr
179d723b313SAndreas Gohr        // 2 points for lot's of formatting
1807db0beafSAnna Dabrowska        if ($this->docArray['formatted'] && $this->docArray['chars'] / $this->docArray['formatted'] < 3) {
1817db0beafSAnna Dabrowska            $this->docArray['err']['manyformat'] = 2;
182d723b313SAndreas Gohr        }
183d723b313SAndreas Gohr
1849068e431SAndreas Gohr        // add up all scores
1857db0beafSAnna Dabrowska        foreach ($this->docArray['err'] as $err => $val) $this->docArray['score'] += $val;
1869068e431SAndreas Gohr
1874ea373cdSAndreas Gohr
1888fce80b1SAndreas Gohr        //we're done here
1897db0beafSAnna Dabrowska        $this->doc = serialize($this->docArray);
1908fce80b1SAndreas Gohr    }
1918fce80b1SAndreas Gohr
1928fce80b1SAndreas Gohr    /**
1938fce80b1SAndreas Gohr     * the format we produce
1948fce80b1SAndreas Gohr     */
19576bbc49cSAnna Dabrowska    public function getFormat()
19676bbc49cSAnna Dabrowska    {
1978fce80b1SAndreas Gohr        return 'qc';
1988fce80b1SAndreas Gohr    }
1998fce80b1SAndreas Gohr
20076bbc49cSAnna Dabrowska    public function internallink($id, $name = null, $search = null, $returnonly = false, $linktype = 'content')
20176bbc49cSAnna Dabrowska    {
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);
2137db0beafSAnna Dabrowska        $this->docArray['link_lengths'][] = $length;
2148d7cf088SAndreas Gohr
2157db0beafSAnna Dabrowska        $this->docArray['internal_links']++;
2167db0beafSAnna Dabrowska        if (!$exists) $this->docArray['broken_links']++;
2170476d180SAndreas Gohr    }
2180476d180SAndreas Gohr
21976bbc49cSAnna Dabrowska    public function externallink($url, $name = null)
22076bbc49cSAnna Dabrowska    {
2217db0beafSAnna Dabrowska        $this->docArray['external_links']++;
222d723b313SAndreas Gohr    }
2238fce80b1SAndreas Gohr
22476bbc49cSAnna Dabrowska    public function header($text, $level, $pos)
22576bbc49cSAnna Dabrowska    {
2267db0beafSAnna Dabrowska        $this->docArray['header_count'][$level]++;
2277db0beafSAnna Dabrowska        $this->docArray['header_struct'][] = $level;
2288fce80b1SAndreas Gohr    }
2298fce80b1SAndreas Gohr
23076bbc49cSAnna Dabrowska    public function smiley($smiley)
23176bbc49cSAnna Dabrowska    {
2327db0beafSAnna Dabrowska        if ($smiley == 'FIXME') $this->docArray['fixme']++;
2338fce80b1SAndreas Gohr    }
2348fce80b1SAndreas Gohr
23576bbc49cSAnna Dabrowska    public function linebreak()
23676bbc49cSAnna Dabrowska    {
2376afc1841Sthesunrise1983        if (!$this->tableopen) {
2387db0beafSAnna Dabrowska            $this->docArray['linebreak']++;
2398fce80b1SAndreas Gohr        }
2406afc1841Sthesunrise1983    }
2416afc1841Sthesunrise1983
242*293182bbSAnna Dabrowska    public function table_open($maxcols = null, $numrows = null, $pos = null) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
24376bbc49cSAnna Dabrowska    {
2446afc1841Sthesunrise1983        $this->tableopen = true;
2456afc1841Sthesunrise1983    }
2466afc1841Sthesunrise1983
247*293182bbSAnna Dabrowska    public function table_close($pos = null) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
24876bbc49cSAnna Dabrowska    {
2496afc1841Sthesunrise1983        $this->tableopen = false;
2506afc1841Sthesunrise1983    }
2518fce80b1SAndreas Gohr
25276bbc49cSAnna Dabrowska    public function hr()
25376bbc49cSAnna Dabrowska    {
2547db0beafSAnna Dabrowska        $this->docArray['hr']++;
2558fce80b1SAndreas Gohr    }
2568fce80b1SAndreas Gohr
257*293182bbSAnna Dabrowska    public function quote_open() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
25876bbc49cSAnna Dabrowska    {
2597db0beafSAnna Dabrowska        $this->docArray['quote_count']++;
2608fce80b1SAndreas Gohr        $this->quotelevel++;
2617db0beafSAnna Dabrowska        $this->docArray['quote_nest'] = max($this->quotelevel, $this->docArray['quote_nest']);
2628fce80b1SAndreas Gohr    }
2638fce80b1SAndreas Gohr
264*293182bbSAnna Dabrowska    public function quote_close() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
26576bbc49cSAnna Dabrowska    {
2668fce80b1SAndreas Gohr        $this->quotelevel--;
2678fce80b1SAndreas Gohr    }
2688fce80b1SAndreas Gohr
269*293182bbSAnna Dabrowska    public function strong_open() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
27076bbc49cSAnna Dabrowska    {
271d723b313SAndreas Gohr        $this->formatting++;
272d723b313SAndreas Gohr    }
2738fce80b1SAndreas Gohr
274*293182bbSAnna Dabrowska    public function strong_close() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
27576bbc49cSAnna Dabrowska    {
276d723b313SAndreas Gohr        $this->formatting--;
277d723b313SAndreas Gohr    }
278d723b313SAndreas Gohr
279*293182bbSAnna Dabrowska    public function emphasis_open() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
28076bbc49cSAnna Dabrowska    {
281d723b313SAndreas Gohr        $this->formatting++;
282d723b313SAndreas Gohr    }
283d723b313SAndreas Gohr
284*293182bbSAnna Dabrowska    public function emphasis_close() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
28576bbc49cSAnna Dabrowska    {
286d723b313SAndreas Gohr        $this->formatting--;
287d723b313SAndreas Gohr    }
288d723b313SAndreas Gohr
289*293182bbSAnna Dabrowska    public function underline_open() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
29076bbc49cSAnna Dabrowska    {
291d723b313SAndreas Gohr        $this->formatting++;
292d723b313SAndreas Gohr    }
293d723b313SAndreas Gohr
294*293182bbSAnna Dabrowska    public function underline_close() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
29576bbc49cSAnna Dabrowska    {
296d723b313SAndreas Gohr        $this->formatting--;
297d723b313SAndreas Gohr    }
298d723b313SAndreas Gohr
29976bbc49cSAnna Dabrowska    public function cdata($text)
30076bbc49cSAnna Dabrowska    {
301d723b313SAndreas Gohr        if (!$this->formatting) return;
302d723b313SAndreas Gohr
303d723b313SAndreas Gohr        $len = utf8_strlen($text);
304d723b313SAndreas Gohr
305d723b313SAndreas Gohr        // 1 point for formattings longer than 500 chars
3067db0beafSAnna Dabrowska        if ($len > 500) $this->docArray['err']['longformat']++;
307d723b313SAndreas Gohr
3084bda998cSAndreas Gohr        // 1 point for each multiformatting
3097db0beafSAnna Dabrowska        if ($this->formatting > 1) $this->docArray['err']['multiformat'] += 1 * ($this->formatting - 1);
3104bda998cSAndreas Gohr
3117db0beafSAnna Dabrowska        $this->docArray['formatted'] += $len;
312d723b313SAndreas Gohr    }
3138fce80b1SAndreas Gohr}
3148fce80b1SAndreas Gohr
3158fce80b1SAndreas Gohr//Setup VIM: ex: et ts=4 enc=utf-8 :
316