Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
ExplainPrinter
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 4
156
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 format
0.00% covered (danger)
0.00%
0 / 25
0.00% covered (danger)
0.00%
0 / 1
30
 formatText
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 processExplain
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2
3namespace CirrusSearch;
4
5use LuceneExplain\ExplainFactory;
6
7/**
8 * Formats the result of elasticsearch explain to a (slightly) more
9 * readable html format than raw json.
10 *
11 * @license GPL-2.0-or-later
12 */
13class ExplainPrinter {
14    /** @var string */
15    private $type;
16    /** @var ExplainFactory */
17    private $explainFactory;
18
19    /**
20     * @param string $type Type of explain to print
21     */
22    public function __construct( $type ) {
23        $this->type = $type;
24        $this->explainFactory = new ExplainFactory;
25    }
26
27    /**
28     * @param mixed $queryResult Elasticsearch result
29     * @return string
30     */
31    public function format( mixed $queryResult ) {
32        $result = [];
33        if ( isset( $queryResult['result']['hits']['hits'] ) ) {
34            $queryResult = [ $queryResult ];
35        }
36        foreach ( $queryResult as $qr ) {
37            $result[] = "<div><h2>{$qr['description']} on {$qr['path']}</h2></div>";
38            foreach ( $qr['result']['hits']['hits'] as $hit ) {
39                $explain = $this->processExplain( $hit['_explanation'] );
40                $result[] =
41                    "<div>" .
42                        "<h3>" . htmlentities( $hit['_source']['title'] ) . "</h3>" .
43                        ( isset( $hit['highlight']['text'][0] ) ? "<div>" . $hit['highlight']['text'][0] . "</div>" : "" ) .
44                        "<table>" .
45                            "<tr>" .
46                                "<td>article id</td>" .
47                                "<td>" . htmlentities( $hit['_id'] ) . "</td>" .
48                            "</tr><tr>" .
49                                "<td>ES score</td>" .
50                                "<td>" . htmlentities( $hit['_score'] ) . "</td>" .
51                            "</tr><tr>" .
52                                "<td>ES explain</td>" .
53                                "<td><pre>" . htmlentities( $explain ) . "</pre></td>" .
54                            "</tr>" .
55                        "</table>" .
56                    "</div>";
57            }
58        }
59
60        return "<div>" . implode( '', $result ) . "</div>";
61    }
62
63    private function formatText( array $explanation, string $indent = "" ): string {
64        $line = $indent . $explanation['value'] . ' | ' . $explanation['description'] . "\n";
65        if ( isset( $explanation['details'] ) ) {
66            foreach ( $explanation['details'] as $subExplanation ) {
67                $line .= $this->formatText( $subExplanation, "$indent    " );
68            }
69        }
70
71        return $line;
72    }
73
74    /**
75     * Only visible for test purposes
76     *
77     * @param array $explanation
78     * @return string
79     */
80    protected function processExplain( array $explanation ) {
81        if ( $this->type === 'verbose' ) {
82            return $this->formatText( $explanation );
83        }
84        $explain = $this->explainFactory->createExplain( $explanation );
85        if ( $this->type === 'hot' ) {
86            return (string)$explain->vectorize();
87        } else {
88            return (string)$explain;
89        }
90    }
91
92}