1<?php
2
3use dokuwiki\Extension\SyntaxPlugin;
4use dokuwiki\plugin\aichat\Chunk;
5use dokuwiki\Search\Indexer;
6
7/**
8 * DokuWiki Plugin aichat (Syntax Component)
9 *
10 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
11 * @author  Andreas Gohr <gohr@cosmocode.de>
12 */
13class syntax_plugin_aichat_similar extends SyntaxPlugin
14{
15    /** @inheritDoc */
16    public function getType()
17    {
18        return 'substition';
19    }
20
21    /** @inheritDoc */
22    public function getPType()
23    {
24        return 'block';
25    }
26
27    /** @inheritDoc */
28    public function getSort()
29    {
30        return 155;
31    }
32
33    /** @inheritDoc */
34    public function connectTo($mode)
35    {
36        $this->Lexer->addSpecialPattern('~~similar~~', $mode, 'plugin_aichat_similar');
37    }
38
39
40    /** @inheritDoc */
41    public function handle($match, $state, $pos, Doku_Handler $handler)
42    {
43        return [];
44    }
45
46    /** @inheritDoc */
47    public function render($mode, Doku_Renderer $renderer, $data)
48    {
49        global $INFO;
50
51        /** @var helper_plugin_aichat $helper */
52        $helper = $this->loadHelper('aichat');
53
54        $id = $INFO['id'];
55
56        $pages = (new Indexer())->getPages();
57        $pos = array_search($id, $pages);
58        if ($pos === false) return true;
59
60        $storage = $helper->getStorage();
61        $chunks = $storage->getPageChunks($id, $pos * 100);
62        $similar = [];
63        foreach ($chunks as $chunk) {
64            $similar += $storage->getSimilarChunks($chunk->getEmbedding(), 10);
65        }
66        $similar = array_unique($similar);
67        $similar = array_filter($similar, static fn($chunk) => $chunk->getPage() !== $id);
68        usort($similar, static fn($a, $b) =>
69            /** @var Chunk $a */
70            /** @var Chunk $b */
71            $b->getScore() <=> $a->getScore());
72
73        if (!$similar) return true;
74
75        $similar = array_slice($similar, 0, 5);
76
77        $renderer->listu_open();
78        foreach ($similar as $chunk) {
79            $renderer->listitem_open(1);
80            $renderer->listcontent_open();
81            $renderer->internallink($chunk->getPage(), null, null, false, 'navigation');
82            $renderer->listcontent_close();
83            $renderer->listitem_close();
84        }
85        $renderer->listu_close();
86
87        return true;
88    }
89}
90