xref: /plugin/combo/action/indexer.php (revision 711d6bd2c63ab43529dc0f6edfa99d8219b82228)
1<?php
2/**
3 * Copyright (c) 2021. ComboStrap, Inc. and its affiliates. All Rights Reserved.
4 *
5 * This source code is licensed under the GPL license found in the
6 * COPYING  file in the root directory of this source tree.
7 *
8 * @license  GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html)
9 * @author   ComboStrap <support@combostrap.com>
10 *
11 *
12 */
13
14require_once(__DIR__ . '/../vendor/autoload.php');
15
16use ComboStrap\Console;
17use ComboStrap\ExceptionCompile;
18use ComboStrap\ExceptionNotFound;
19use ComboStrap\ExceptionTimeOut;
20use ComboStrap\ExecutionContext;
21use ComboStrap\FileSystems;
22use ComboStrap\Lock;
23use ComboStrap\LogUtility;
24use ComboStrap\MarkupPath;
25use ComboStrap\Meta\Store\MetadataDbStore;
26use ComboStrap\Meta\Store\MetadataDokuWikiStore;
27use ComboStrap\PluginUtility;
28use ComboStrap\Reference;
29use ComboStrap\References;
30
31
32/**
33 * Process metadata put them in the sqlite database (ie create derived index)
34 *
35 *
36 * For the replication, this is the equivalent of the dokuwiki {@link \dokuwiki\Search\Indexer}
37 * (textual search engine, plus metadata index)
38 *
39 * Note that you can disable a page to go into the index
40 * via the `internal index` metadata. See {@link idx_addPage()}
41 * ```
42 * $indexenabled = p_get_metadata($page, 'internal index', METADATA_RENDER_UNLIMITED);
43 * ```
44 */
45class action_plugin_combo_indexer extends DokuWiki_Action_Plugin
46{
47
48    /**
49     * Bad canonical for now as we will add the
50     * {@link \ComboStrap\ComboFs} system
51     * but it's still a valid page
52     */
53    const CANONICAL = "replication";
54
55    public function register(Doku_Event_Handler $controller)
56    {
57
58        /**
59         * We do it after because if there is an error
60         * We will not stop the Dokuwiki Processing
61         *
62         * We could do it after
63         * https://www.dokuwiki.org/devel:event:parser_metadata_render
64         * but it would then not be async
65         *
66         * Note: We support other extension for markup
67         * but dokuwiki does not index other extension
68         * in {@link idx_addPage} (page is the id)
69         */
70        $controller->register_hook('INDEXER_PAGE_ADD', 'AFTER', $this, 'indexViaIndexerAdd', array());
71
72        /**
73         *
74         * https://www.dokuwiki.org/devel:event:parser_metadata_render
75         *
76         */
77
78
79
80    }
81
82    /**
83     * @throws ExceptionCompile
84     */
85    public function indexViaIndexerAdd(Doku_Event $event, $param)
86    {
87
88
89        $lock = Lock::create("combo-indexer");
90        try {
91            $lock->acquire();
92        } catch (ExceptionTimeOut $e) {
93            // process running
94            return;
95        }
96
97        /**
98         * Get the q flag of the indexer
99         * php bin/indexer.php -q
100         */
101        $verbose = true;
102        if (PHP_SAPI === 'cli') {
103            global $argv;
104            foreach ($argv as $arg) {
105                if ($arg === '-q') {
106                    // Script was started with the -q flag.
107                    $verbose = false;
108                    break;
109                }
110            }
111        }
112
113        if ($verbose) echo 'ComboIndexer(): Indexer started'. DOKU_LF;
114
115        try {
116            /**
117             * Check that the actual page has analytics data
118             * (if there is a cache, it's pretty quick)
119             */
120            $id = $event->data['page'];
121            $page = MarkupPath::createMarkupFromId($id);
122
123            /**
124             * From {@link idx_addPage}
125             * They receive even the deleted page
126             */
127            $databasePage = $page->getDatabasePage();
128            if (!FileSystems::exists($page)) {
129                $databasePage->delete();
130                return;
131            }
132
133            if ($databasePage->shouldReplicate()) {
134                try {
135                    $databasePage->replicate();
136                } catch (ExceptionCompile $e) {
137                    if (PluginUtility::isDevOrTest()) {
138                        // to get the stack trace
139                        throw $e;
140                    }
141                    $message = "Error with the database replication for the page ($page). " . $e->getMessage();
142                    if (Console::isConsoleRun()) {
143                        throw new ExceptionCompile($message);
144                    } else {
145                        LogUtility::error($message);
146                    }
147                }
148            }
149
150        } finally {
151            if ($verbose) echo 'ComboIndexer(): Indexer finished'. DOKU_LF;
152            $lock->release();
153        }
154
155    }
156
157
158    function indexViaMetadataRendering(Doku_Event $event, $params)
159    {
160
161        try {
162            $wikiPath = ExecutionContext::getActualOrCreateFromEnv()
163                ->getExecutingWikiPath();
164        } catch (ExceptionNotFound $e) {
165            // markup string run
166            return;
167        }
168
169        $page = MarkupPath::createPageFromPathObject($wikiPath);
170
171        $references = References::createFromResource($page)
172            ->setReadStore(MetadataDokuWikiStore::class);
173
174        $internalIdReferences = $event->data['current']['relation']['references'];
175        foreach ($internalIdReferences as $internalIdReferenceValue => $internalIdReferenceExist) {
176            $ref = Reference::createFromResource($page)
177                ->setReadStore(MetadataDokuWikiStore::class)
178                ->setFromStoreValueWithoutException($internalIdReferenceValue);
179            try {
180                $references->addRow([$ref]);
181            } catch (ExceptionNotFound $e) {
182                LogUtility::internalError("The identifier and the value identifier should be known at this stage", self::CANONICAL, $e);
183            }
184        }
185
186        try {
187            // persist to database
188            $references
189                ->setWriteStore(MetadataDbStore::class)
190                ->persist();
191        } catch (ExceptionCompile $e) {
192            LogUtility::warning("Reference error when persisting to the file system store: " . $e->getMessage(), self::CANONICAL, $e);
193        }
194
195    }
196
197
198}
199
200
201
202