xref: /plugin/combo/action/indexer.php (revision a183757cb9ca50a5e3aba0893205ee1a377809e7)
104fd306cSNickeau<?php
204fd306cSNickeau/**
304fd306cSNickeau * Copyright (c) 2021. ComboStrap, Inc. and its affiliates. All Rights Reserved.
404fd306cSNickeau *
504fd306cSNickeau * This source code is licensed under the GPL license found in the
604fd306cSNickeau * COPYING  file in the root directory of this source tree.
704fd306cSNickeau *
804fd306cSNickeau * @license  GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html)
904fd306cSNickeau * @author   ComboStrap <support@combostrap.com>
1004fd306cSNickeau *
1104fd306cSNickeau *
1204fd306cSNickeau */
1304fd306cSNickeau
14ad54dffdSgerardnicorequire_once(__DIR__ . '/../vendor/autoload.php');
15ad54dffdSgerardnico
1604fd306cSNickeauuse ComboStrap\Console;
1704fd306cSNickeauuse ComboStrap\ExceptionCompile;
1804fd306cSNickeauuse ComboStrap\ExceptionNotFound;
192becc3acSgerardnicouse ComboStrap\ExceptionTimeOut;
2004fd306cSNickeauuse ComboStrap\ExecutionContext;
2104fd306cSNickeauuse ComboStrap\FileSystems;
222becc3acSgerardnicouse ComboStrap\Lock;
2304fd306cSNickeauuse ComboStrap\LogUtility;
2404fd306cSNickeauuse ComboStrap\MarkupPath;
2504fd306cSNickeauuse ComboStrap\Meta\Store\MetadataDbStore;
2604fd306cSNickeauuse ComboStrap\Meta\Store\MetadataDokuWikiStore;
2704fd306cSNickeauuse ComboStrap\PluginUtility;
2804fd306cSNickeauuse ComboStrap\Reference;
2904fd306cSNickeauuse ComboStrap\References;
3004fd306cSNickeau
3104fd306cSNickeau
3204fd306cSNickeau/**
3304fd306cSNickeau * Process metadata put them in the sqlite database (ie create derived index)
3404fd306cSNickeau *
3504fd306cSNickeau *
3604fd306cSNickeau * For the replication, this is the equivalent of the dokuwiki {@link \dokuwiki\Search\Indexer}
3704fd306cSNickeau * (textual search engine, plus metadata index)
3804fd306cSNickeau *
3904fd306cSNickeau * Note that you can disable a page to go into the index
4004fd306cSNickeau * via the `internal index` metadata. See {@link idx_addPage()}
4104fd306cSNickeau * ```
4204fd306cSNickeau * $indexenabled = p_get_metadata($page, 'internal index', METADATA_RENDER_UNLIMITED);
4304fd306cSNickeau * ```
4404fd306cSNickeau */
4504fd306cSNickeauclass action_plugin_combo_indexer extends DokuWiki_Action_Plugin
4604fd306cSNickeau{
4704fd306cSNickeau
4804fd306cSNickeau    /**
4904fd306cSNickeau     * Bad canonical for now as we will add the
5004fd306cSNickeau     * {@link \ComboStrap\ComboFs} system
5104fd306cSNickeau     * but it's still a valid page
5204fd306cSNickeau     */
5304fd306cSNickeau    const CANONICAL = "replication";
5404fd306cSNickeau
5504fd306cSNickeau    public function register(Doku_Event_Handler $controller)
5604fd306cSNickeau    {
5704fd306cSNickeau
5804fd306cSNickeau        /**
5904fd306cSNickeau         * We do it after because if there is an error
6004fd306cSNickeau         * We will not stop the Dokuwiki Processing
6104fd306cSNickeau         *
6204fd306cSNickeau         * We could do it after
6304fd306cSNickeau         * https://www.dokuwiki.org/devel:event:parser_metadata_render
6404fd306cSNickeau         * but it would then not be async
6504fd306cSNickeau         *
6604fd306cSNickeau         * Note: We support other extension for markup
6704fd306cSNickeau         * but dokuwiki does not index other extension
6804fd306cSNickeau         * in {@link idx_addPage} (page is the id)
6904fd306cSNickeau         */
7004fd306cSNickeau        $controller->register_hook('INDEXER_PAGE_ADD', 'AFTER', $this, 'indexViaIndexerAdd', array());
7104fd306cSNickeau
7204fd306cSNickeau        /**
7304fd306cSNickeau         *
7404fd306cSNickeau         * https://www.dokuwiki.org/devel:event:parser_metadata_render
7504fd306cSNickeau         *
7604fd306cSNickeau         */
7704fd306cSNickeau
7804fd306cSNickeau
7904fd306cSNickeau
8004fd306cSNickeau    }
8104fd306cSNickeau
8204fd306cSNickeau    /**
8304fd306cSNickeau     * @throws ExceptionCompile
8404fd306cSNickeau     */
8504fd306cSNickeau    public function indexViaIndexerAdd(Doku_Event $event, $param)
8604fd306cSNickeau    {
8704fd306cSNickeau
88*a183757cSNico
892becc3acSgerardnico        $lock = Lock::create("combo-indexer");
902becc3acSgerardnico        try {
912becc3acSgerardnico            $lock->acquire();
922becc3acSgerardnico        } catch (ExceptionTimeOut $e) {
932becc3acSgerardnico            // process running
942becc3acSgerardnico            return;
952becc3acSgerardnico        }
962becc3acSgerardnico
97*a183757cSNico        /**
98*a183757cSNico         * Get the q flag of the indexer
99*a183757cSNico         * php bin/indexer.php -q
100*a183757cSNico         */
101*a183757cSNico        $verbose = true;
102*a183757cSNico        if (PHP_SAPI === 'cli') {
103*a183757cSNico            global $argv;
104*a183757cSNico            foreach ($argv as $arg) {
105*a183757cSNico                if ($arg === '-q') {
106*a183757cSNico                    // Script was started with the -q flag.
107*a183757cSNico                    $verbose = false;
108*a183757cSNico                    break;
109*a183757cSNico                }
110*a183757cSNico            }
111*a183757cSNico        }
112*a183757cSNico
113*a183757cSNico        if ($verbose) echo 'ComboIndexer(): Indexer started'. DOKU_LF;
114ea72c629Sgerardnico
1152becc3acSgerardnico        try {
11604fd306cSNickeau            /**
11704fd306cSNickeau             * Check that the actual page has analytics data
11804fd306cSNickeau             * (if there is a cache, it's pretty quick)
11904fd306cSNickeau             */
12004fd306cSNickeau            $id = $event->data['page'];
12104fd306cSNickeau            $page = MarkupPath::createMarkupFromId($id);
12204fd306cSNickeau
12304fd306cSNickeau            /**
12404fd306cSNickeau             * From {@link idx_addPage}
12504fd306cSNickeau             * They receive even the deleted page
12604fd306cSNickeau             */
12704fd306cSNickeau            $databasePage = $page->getDatabasePage();
12804fd306cSNickeau            if (!FileSystems::exists($page)) {
12904fd306cSNickeau                $databasePage->delete();
13004fd306cSNickeau                return;
13104fd306cSNickeau            }
13204fd306cSNickeau
13304fd306cSNickeau            if ($databasePage->shouldReplicate()) {
13404fd306cSNickeau                try {
13504fd306cSNickeau                    $databasePage->replicate();
13604fd306cSNickeau                } catch (ExceptionCompile $e) {
13704fd306cSNickeau                    if (PluginUtility::isDevOrTest()) {
13804fd306cSNickeau                        // to get the stack trace
13904fd306cSNickeau                        throw $e;
14004fd306cSNickeau                    }
14104fd306cSNickeau                    $message = "Error with the database replication for the page ($page). " . $e->getMessage();
14204fd306cSNickeau                    if (Console::isConsoleRun()) {
14304fd306cSNickeau                        throw new ExceptionCompile($message);
14404fd306cSNickeau                    } else {
14504fd306cSNickeau                        LogUtility::error($message);
14604fd306cSNickeau                    }
14704fd306cSNickeau                }
14804fd306cSNickeau            }
14904fd306cSNickeau
1502becc3acSgerardnico        } finally {
151*a183757cSNico            if ($verbose) echo 'ComboIndexer(): Indexer finished'. DOKU_LF;
1522becc3acSgerardnico            $lock->release();
1532becc3acSgerardnico        }
15404fd306cSNickeau
15504fd306cSNickeau    }
15604fd306cSNickeau
15704fd306cSNickeau
15804fd306cSNickeau    function indexViaMetadataRendering(Doku_Event $event, $params)
15904fd306cSNickeau    {
16004fd306cSNickeau
16104fd306cSNickeau        try {
16204fd306cSNickeau            $wikiPath = ExecutionContext::getActualOrCreateFromEnv()
16304fd306cSNickeau                ->getExecutingWikiPath();
16404fd306cSNickeau        } catch (ExceptionNotFound $e) {
16504fd306cSNickeau            // markup string run
16604fd306cSNickeau            return;
16704fd306cSNickeau        }
16804fd306cSNickeau
16904fd306cSNickeau        $page = MarkupPath::createPageFromPathObject($wikiPath);
17004fd306cSNickeau
17104fd306cSNickeau        $references = References::createFromResource($page)
17204fd306cSNickeau            ->setReadStore(MetadataDokuWikiStore::class);
17304fd306cSNickeau
17404fd306cSNickeau        $internalIdReferences = $event->data['current']['relation']['references'];
17504fd306cSNickeau        foreach ($internalIdReferences as $internalIdReferenceValue => $internalIdReferenceExist) {
17604fd306cSNickeau            $ref = Reference::createFromResource($page)
17704fd306cSNickeau                ->setReadStore(MetadataDokuWikiStore::class)
17804fd306cSNickeau                ->setFromStoreValueWithoutException($internalIdReferenceValue);
17904fd306cSNickeau            try {
18004fd306cSNickeau                $references->addRow([$ref]);
18104fd306cSNickeau            } catch (ExceptionNotFound $e) {
18204fd306cSNickeau                LogUtility::internalError("The identifier and the value identifier should be known at this stage", self::CANONICAL, $e);
18304fd306cSNickeau            }
18404fd306cSNickeau        }
18504fd306cSNickeau
18604fd306cSNickeau        try {
18704fd306cSNickeau            // persist to database
18804fd306cSNickeau            $references
18904fd306cSNickeau                ->setWriteStore(MetadataDbStore::class)
19004fd306cSNickeau                ->persist();
19104fd306cSNickeau        } catch (ExceptionCompile $e) {
19204fd306cSNickeau            LogUtility::warning("Reference error when persisting to the file system store: " . $e->getMessage(), self::CANONICAL, $e);
19304fd306cSNickeau        }
19404fd306cSNickeau
19504fd306cSNickeau    }
19604fd306cSNickeau
19704fd306cSNickeau
19804fd306cSNickeau}
19904fd306cSNickeau
20004fd306cSNickeau
20104fd306cSNickeau
202