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