History log of /dokuwiki/inc/Search/ (Results 1 – 25 of 143)
Revision Date Author Comments
(<<< Hide modified files)
(Show modified files >>>)
846f53c108-Jul-2026 Andreas Gohr <gohr@cosmocode.de>

fix(search): lock the metadata registry read-modify-write

updateMetadataRegistry() read metadata.idx, merged in new keys and wrote
the file back without holding a lock across the sequence. Two index

fix(search): lock the metadata registry read-modify-write

updateMetadataRegistry() read metadata.idx, merged in new keys and wrote
the file back without holding a lock across the sequence. Two indexer
processes each registering a different new key could both read the same
registry and the later writer would clobber the other's key, dropping it.
A dropped key is not cleared from its collection on deletePage(), leaving
orphaned index entries.

Guard the whole read-merge-write with a dedicated metadata lock so
concurrent registrations can no longer lose a key.

show more ...

d9043e7808-Jul-2026 Andreas Gohr <gohr@cosmocode.de>

fix(search): make DirectCollection::getEntitiesWithData() linear

The method resolved each entity name with a separate retrieveRow() call,
each of which rescans the entity index from the start, makin

fix(search): make DirectCollection::getEntitiesWithData() linear

The method resolved each entity name with a separate retrieveRow() call,
each of which rescans the entity index from the start, making the whole
operation quadratic in the number of entities. This runs on
MetadataSearch::getPages('title') and hurts large wikis. Collect the entity
IDs in one pass and resolve their names with a single batched retrieveRows()
read instead.

show more ...

45fa8bb208-Jul-2026 Andreas Gohr <gohr@cosmocode.de>

fix(search): stop FileIndex::retrieveRows() scanning past the last row

The early-exit check compared the array_shift() result against false, but
array_shift() returns null on an empty array, so the

fix(search): stop FileIndex::retrieveRows() scanning past the last row

The early-exit check compared the array_shift() result against false, but
array_shift() returns null on an empty array, so the break never fired and
every call read the index file to EOF after collecting the last requested
row. Compare against null and skip the file entirely when nothing is
requested.

show more ...

61dea71008-Jul-2026 Andreas Gohr <gohr@cosmocode.de>

fix(search): wait for a contended index lock and apply dperm

The Lock rewrite (c66b5ec65) made Lock::acquire() fail immediately when the
lock directory already existed, where the old indexer lock re

fix(search): wait for a contended index lock and apply dperm

The Lock rewrite (c66b5ec65) made Lock::acquire() fail immediately when the
lock directory already existed, where the old indexer lock retried until the
holder released it. Concurrent saves or indexer runs then aborted indexing
instead of serializing (recoverable only via the .indexed tag on the next
edit), and the lock directory was created without the configured directory
permissions, unlike every other directory DokuWiki creates.

Mirror the io_lock() convention: wait for a contended lock, bounded by a
tunable wait timeout, before throwing; keep clearing locks older than five
minutes as stale; and chmod the new lock directory to $conf['dperm']. The
give-up path still throws IndexLockException, so the self-healing retry via
the .indexed tag is unchanged.

show more ...


/dokuwiki/.github/workflows/testLinux.yml
/dokuwiki/.github/workflows/testWindows.yml
/dokuwiki/_test/tests/ChangeLog/MediaChangeLogTest.php
/dokuwiki/_test/tests/ChangeLog/PageChangeLogTest.php
/dokuwiki/_test/tests/Feed/FeedParserTest.php
/dokuwiki/_test/tests/File/MediaFileTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/QuotesTest.php
/dokuwiki/_test/tests/Remote/ApiCoreAclCheckTest.php
/dokuwiki/_test/tests/Search/Index/LockTest.php
/dokuwiki/_test/tests/Ui/Media/DisplayTest.php
/dokuwiki/_test/tests/inc/common_saveWikiText.test.php
/dokuwiki/_test/tests/inc/httputils_xaccel.test.php
/dokuwiki/_test/tests/inc/infoutils_getversiondata.test.php
/dokuwiki/_test/tests/inc/media_resize.test.php
/dokuwiki/composer.json
/dokuwiki/composer.lock
/dokuwiki/inc/Cache/CacheImageMod.php
/dokuwiki/inc/ChangeLog/ChangeLog.php
/dokuwiki/inc/ChangeLog/MediaChangeLog.php
/dokuwiki/inc/ChangeLog/PageChangeLog.php
/dokuwiki/inc/Feed/FeedParserFile.php
/dokuwiki/inc/File/MediaFile.php
/dokuwiki/inc/Parsing/ModeRegistry.php
/dokuwiki/inc/Parsing/ParserMode/GfmListblock.php
/dokuwiki/inc/Parsing/ParserMode/Quotes.php
/dokuwiki/inc/Remote/ApiCore.php
Index/Lock.php
/dokuwiki/inc/Subscriptions/BulkSubscriptionSender.php
/dokuwiki/inc/Ui/Admin.php
/dokuwiki/inc/Ui/Media/Display.php
/dokuwiki/inc/Ui/MediaDiff.php
/dokuwiki/inc/httputils.php
/dokuwiki/inc/infoutils.php
/dokuwiki/inc/media.php
/dokuwiki/inc/template.php
/dokuwiki/lib/exe/fetch.php
/dokuwiki/lib/plugins/extension/Local.php
/dokuwiki/lib/plugins/extension/_test/LocalTest.php
/dokuwiki/lib/plugins/info/syntax.php
/dokuwiki/lib/scripts/edit.js
/dokuwiki/vendor/composer/installed.json
/dokuwiki/vendor/composer/installed.php
/dokuwiki/vendor/splitbrain/slika/README.md
/dokuwiki/vendor/splitbrain/slika/src/Adapter.php
/dokuwiki/vendor/splitbrain/slika/src/GdAdapter.php
/dokuwiki/vendor/splitbrain/slika/src/ImageInfo.php
/dokuwiki/vendor/splitbrain/slika/src/ImageMagickAdapter.php
7595d8da06-Jul-2026 splitbrain <86426+splitbrain@users.noreply.github.com>

�� Rector and PHPCS fixes

ebaa848105-Jul-2026 Andreas Gohr <andi@splitbrain.org>

fix(search): restore histogram() as a Collection method with a BC shim

The indexer rework dropped Doku_Indexer::histogram(), which plugins reach
through idx_get_indexer()->histogram() to build tag c

fix(search): restore histogram() as a Collection method with a BC shim

The indexer rework dropped Doku_Indexer::histogram(), which plugins reach
through idx_get_indexer()->histogram() to build tag clouds (e.g. tagfilter
via the 'subject' metadata index). Calling it fatalled through
LegacyIndexer::__call as an undefined method.

Add histogram() to AbstractCollection: it sums each token's frequency across
all entities and returns them ordered by frequency, filtered by min/max/minlen,
handling both length-split (fulltext) and single-group (metadata) collections.
DirectCollection overrides it for the 1:1 title case (count shared values).
LegacyIndexer::histogram() is a deprecated shim dispatching by $key to the
matching collection.

show more ...

9e4de2f705-Jul-2026 Andreas Gohr <andi@splitbrain.org>

fix(search): don't let collections release a caller-owned index lock

Indexer::addPage() locks the page index once and hands the same instance to
several collections, each of which lock() and unlock(

fix(search): don't let collections release a caller-owned index lock

Indexer::addPage() locks the page index once and hands the same instance to
several collections, each of which lock() and unlock() it around their work.

AbstractCollection::lock() locked and tracked every index for later release.
When a shared AbstractIndex was already locked by the caller, locking it again
was a no-op but the collection still tracked it, so the collection's unlock()
released the caller's lock and flipped the shared index read-only. Each later
collection then re-acquired and re-released it, leaving windows in which another
process could grab the page lock mid-operation; contention could abort addPage()
with the title index updated but the fulltext index stale.

Treat a shared index that is already writable as owned by its creator: leave its
lock untouched and only manage the locks the collection acquires itself.

Add a regression test asserting a caller-held index lock survives repeated
collection lock()/unlock() cycles.

show more ...

4e61aa7105-Jul-2026 Andreas Gohr <andi@splitbrain.org>

fix(search): create index lock directories inside data/locks

Index locks were built by concatenating the configured lock directory and
the index name without a path separator.

That produced paths l

fix(search): create index lock directories inside data/locks

Index locks were built by concatenating the configured lock directory and
the index name without a path separator.

That produced paths like data/lockspage.index instead of
data/locks/page.index, so index lock directories were created in the
data root rather than inside the configured lock directory.

Fix this by joining the lock directory and index name with an explicit
slash, and update the lock test to assert the correct location and guard
against the old broken path.

show more ...

bc12b8fe05-Jul-2026 Andreas Gohr <andi@splitbrain.org>

fix(search): read split index suffixes correctly

AbstractIndex::max() used /(\d)+\.idx$/ to determine the highest split
index suffix. For filenames like w10.idx or w12.idx that regex captured
only t

fix(search): read split index suffixes correctly

AbstractIndex::max() used /(\d)+\.idx$/ to determine the highest split
index suffix. For filenames like w10.idx or w12.idx that regex captured
only the last digit, so the maximum token-length group was truncated to 9.
Wildcard searches therefore skipped all fulltext index shards for words
with 10 or more characters.

Tighten the match to the basename and require the current index name
followed immediately by digits: ^<idx>(\d+)\.idx$. This captures the full
numeric suffix and also avoids counting unrelated index families that
share the same prefix, such as treating wiki2.idx as a numbered shard of
the w index.

Add regressions for both behaviors: multi-digit suffixes are parsed
correctly, and same-prefix indexes are ignored when determining the
maximum shard number.

show more ...

b1f7ba6405-Jul-2026 Andreas Gohr <andi@splitbrain.org>

fix(search): fatals on invalid short wildcard terms

Searches such as "wiki a*" could crash in QueryEvaluator::opAnd() with
a TypeError. The query parser still emitted the wildcard term, but the
full

fix(search): fatals on invalid short wildcard terms

Searches such as "wiki a*" could crash in QueryEvaluator::opAnd() with
a TypeError. The query parser still emitted the wildcard term, but the
fulltext search later dropped it because its non-wildcard base was below
the minimum search term length.

That left the evaluator with an AND operator whose right-hand operand was
missing, causing a stack underflow during RPN evaluation.

Fix this in two places:
- filter invalid short wildcard terms already in Tokenizer::getWords()
when wildcard parsing is enabled, so they never enter the parsed query
- harden QueryEvaluator against missing operands for AND/OR/NOT to avoid
fatals if tokens disappear during later processing

Add regression tests covering the parser output for "wiki a*" and the
evaluator behavior when an operand is missing.

show more ...

e282ae5505-Jul-2026 Andreas Gohr <andi@splitbrain.org>

fix(search): search index corruption in updateTuple

Require an end-of-tuple boundary when removing an existing tuple in
TupleOps::updateTuple(), so updating row ID 17 no longer corrupts
tuples for I

fix(search): search index corruption in updateTuple

Require an end-of-tuple boundary when removing an existing tuple in
TupleOps::updateTuple(), so updating row ID 17 no longer corrupts
tuples for IDs like 170 or 171.

Add regression tests covering both replacement and deletion when one
numeric row ID is a decimal prefix of another.

show more ...


/dokuwiki/_test/bootstrap.php
/dokuwiki/_test/composer.lock
/dokuwiki/_test/rector.php
/dokuwiki/_test/tests/ChangeLog/PageChangeLogTest.php
/dokuwiki/_test/tests/DraftTest.php
/dokuwiki/_test/tests/Extension/PluginRenderTextTest.php
/dokuwiki/_test/tests/Feed/FeedParserTest.php
/dokuwiki/_test/tests/Form/TextareaElementTest.php
/dokuwiki/_test/tests/Parsing/HandlerTest.php
/dokuwiki/_test/tests/Parsing/Helpers/CodeTest.php
/dokuwiki/_test/tests/Parsing/Helpers/EscapeTest.php
/dokuwiki/_test/tests/Parsing/Helpers/HtmlEntityTest.php
/dokuwiki/_test/tests/Parsing/Helpers/LinkTest.php
/dokuwiki/_test/tests/Parsing/Helpers/MediaTest.php
/dokuwiki/_test/tests/Parsing/Lexer/LexerTest.php
/dokuwiki/_test/tests/Parsing/Lexer/ParallelRegexTest.php
/dokuwiki/_test/tests/Parsing/Lexer/RecordingHandler.php
/dokuwiki/_test/tests/Parsing/LocaleXhtmlTest.php
/dokuwiki/_test/tests/Parsing/Markdown/GfmSpecTest.php
/dokuwiki/_test/tests/Parsing/Markdown/SpecCompatRenderer.php
/dokuwiki/_test/tests/Parsing/Markdown/SpecReader.php
/dokuwiki/_test/tests/Parsing/Markdown/SpecReaderTest.php
/dokuwiki/_test/tests/Parsing/Markdown/gfm-spec/LICENSE
/dokuwiki/_test/tests/Parsing/Markdown/gfm-spec/README.md
/dokuwiki/_test/tests/Parsing/Markdown/gfm-spec/skip.php
/dokuwiki/_test/tests/Parsing/Markdown/gfm-spec/spec.txt
/dokuwiki/_test/tests/Parsing/ModeRegistryTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/CamelcaselinkTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/CodeTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/EmaillinkTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/ExternallinkTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/FileTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/FilelinkTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/FootnoteTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/FormattingTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmBacktickDoubleTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmBacktickSingleTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmCodeTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmDeletedTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmEmphasisStrongTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmEmphasisStrongUnderscoreTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmEmphasisTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmEmphasisUnderscoreTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmEscapeTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmFileTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmHeaderTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmHrTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmHtmlEntityTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmLinebreakTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmLinkTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmListblockTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmMediaTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmQuoteTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmStrongUnderscoreTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/GfmTableTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/HeadersTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/InternallinkTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/ListsTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/MediaTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/ParserTestBase.php
/dokuwiki/_test/tests/Parsing/ParserMode/PreformattedTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/ReplacementsTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/RssTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/WindowssharelinkTest.php
/dokuwiki/_test/tests/Parsing/SyntaxOverrideTest.php
/dokuwiki/_test/tests/Remote/ApiCoreAclCheckTest.php
/dokuwiki/_test/tests/Search/BacklinksTest.php
/dokuwiki/_test/tests/Search/Index/TupleOpsTest.php
/dokuwiki/_test/tests/Ui/PageDiffTest.php
/dokuwiki/_test/tests/inc/IpTest.php
/dokuwiki/_test/tests/inc/httputils_xaccel.test.php
/dokuwiki/_test/tests/lib/exe/ajax_requests.test.php
/dokuwiki/composer.lock
/dokuwiki/conf/dokuwiki.php
/dokuwiki/data/deleted.files
/dokuwiki/data/pages/wiki/syntax.txt
/dokuwiki/inc/Action/Register.php
/dokuwiki/inc/Ajax.php
/dokuwiki/inc/Cache/CacheInstructions.php
/dokuwiki/inc/Cache/CacheParser.php
/dokuwiki/inc/Cache/CacheRenderer.php
/dokuwiki/inc/ChangeLog/ChangeLog.php
/dokuwiki/inc/ChangeLog/MediaChangeLog.php
/dokuwiki/inc/ChangeLog/PageChangeLog.php
/dokuwiki/inc/Extension/AuthPlugin.php
/dokuwiki/inc/Extension/PluginInterface.php
/dokuwiki/inc/Extension/PluginTrait.php
/dokuwiki/inc/Extension/SyntaxPlugin.php
/dokuwiki/inc/Feed/FeedParserFile.php
/dokuwiki/inc/Form/TextareaElement.php
/dokuwiki/inc/Ip.php
/dokuwiki/inc/JpegMeta.php
/dokuwiki/inc/Parsing/Handler.php
/dokuwiki/inc/Parsing/Handler/AbstractListsRewriter.php
/dokuwiki/inc/Parsing/Handler/Block.php
/dokuwiki/inc/Parsing/Handler/GfmLists.php
/dokuwiki/inc/Parsing/Handler/GfmTable.php
/dokuwiki/inc/Parsing/Handler/Lists.php
/dokuwiki/inc/Parsing/Handler/Preformatted.php
/dokuwiki/inc/Parsing/Helpers/Code.php
/dokuwiki/inc/Parsing/Helpers/Escape.php
/dokuwiki/inc/Parsing/Helpers/HtmlEntity.php
/dokuwiki/inc/Parsing/Helpers/Link.php
/dokuwiki/inc/Parsing/Helpers/Media.php
/dokuwiki/inc/Parsing/Lexer/Lexer.php
/dokuwiki/inc/Parsing/Lexer/ParallelRegex.php
/dokuwiki/inc/Parsing/ModeRegistry.php
/dokuwiki/inc/Parsing/Parser.php
/dokuwiki/inc/Parsing/ParserMode/AbstractFormatting.php
/dokuwiki/inc/Parsing/ParserMode/AbstractMode.php
/dokuwiki/inc/Parsing/ParserMode/Base.php
/dokuwiki/inc/Parsing/ParserMode/Code.php
/dokuwiki/inc/Parsing/ParserMode/Deleted.php
/dokuwiki/inc/Parsing/ParserMode/Emphasis.php
/dokuwiki/inc/Parsing/ParserMode/Eol.php
/dokuwiki/inc/Parsing/ParserMode/Externallink.php
/dokuwiki/inc/Parsing/ParserMode/Footnote.php
/dokuwiki/inc/Parsing/ParserMode/GfmBacktickDouble.php
/dokuwiki/inc/Parsing/ParserMode/GfmBacktickSingle.php
/dokuwiki/inc/Parsing/ParserMode/GfmCode.php
/dokuwiki/inc/Parsing/ParserMode/GfmDeleted.php
/dokuwiki/inc/Parsing/ParserMode/GfmEmphasis.php
/dokuwiki/inc/Parsing/ParserMode/GfmEmphasisStrong.php
/dokuwiki/inc/Parsing/ParserMode/GfmEmphasisStrongUnderscore.php
/dokuwiki/inc/Parsing/ParserMode/GfmEmphasisUnderscore.php
/dokuwiki/inc/Parsing/ParserMode/GfmEscape.php
/dokuwiki/inc/Parsing/ParserMode/GfmFile.php
/dokuwiki/inc/Parsing/ParserMode/GfmHeader.php
/dokuwiki/inc/Parsing/ParserMode/GfmHr.php
/dokuwiki/inc/Parsing/ParserMode/GfmHtmlEntity.php
/dokuwiki/inc/Parsing/ParserMode/GfmLinebreak.php
/dokuwiki/inc/Parsing/ParserMode/GfmLink.php
/dokuwiki/inc/Parsing/ParserMode/GfmListblock.php
/dokuwiki/inc/Parsing/ParserMode/GfmMedia.php
/dokuwiki/inc/Parsing/ParserMode/GfmQuote.php
/dokuwiki/inc/Parsing/ParserMode/GfmStrongUnderscore.php
/dokuwiki/inc/Parsing/ParserMode/GfmTable.php
/dokuwiki/inc/Parsing/ParserMode/Header.php
/dokuwiki/inc/Parsing/ParserMode/Internallink.php
/dokuwiki/inc/Parsing/ParserMode/Listblock.php
/dokuwiki/inc/Parsing/ParserMode/Media.php
/dokuwiki/inc/Parsing/ParserMode/Monospace.php
/dokuwiki/inc/Parsing/ParserMode/Preformatted.php
/dokuwiki/inc/Parsing/ParserMode/Strong.php
/dokuwiki/inc/Parsing/ParserMode/Subscript.php
/dokuwiki/inc/Parsing/ParserMode/Superscript.php
/dokuwiki/inc/Parsing/ParserMode/Table.php
/dokuwiki/inc/Parsing/ParserMode/Underline.php
/dokuwiki/inc/Remote/ApiCore.php
/dokuwiki/inc/Remote/JsonRpcServer.php
/dokuwiki/inc/Remote/XmlRpcServer.php
Index/TupleOps.php
/dokuwiki/inc/Ui/Diff.php
/dokuwiki/inc/Ui/Search.php
/dokuwiki/inc/deprecated.php
/dokuwiki/inc/httputils.php
/dokuwiki/inc/lang/cs/lang.php
/dokuwiki/inc/media.php
/dokuwiki/inc/parser/metadata.php
/dokuwiki/inc/parser/renderer.php
/dokuwiki/inc/parser/xhtml.php
/dokuwiki/inc/parserutils.php
/dokuwiki/inc/template.php
/dokuwiki/lib/exe/css.php
/dokuwiki/lib/exe/js.php
/dokuwiki/lib/plugins/acl/admin.php
/dokuwiki/lib/plugins/authad/auth.php
/dokuwiki/lib/plugins/authldap/auth.php
/dokuwiki/lib/plugins/authpdo/auth.php
/dokuwiki/lib/plugins/authplain/_test/userdata.test.php
/dokuwiki/lib/plugins/authplain/auth.php
/dokuwiki/lib/plugins/config/core/Setting/Setting.php
/dokuwiki/lib/plugins/config/core/Setting/SettingArray.php
/dokuwiki/lib/plugins/config/core/Setting/SettingEmail.php
/dokuwiki/lib/plugins/config/core/Setting/SettingImConvert.php
/dokuwiki/lib/plugins/config/core/Setting/SettingMulticheckbox.php
/dokuwiki/lib/plugins/config/core/Setting/SettingMultichoice.php
/dokuwiki/lib/plugins/config/core/Setting/SettingOnoff.php
/dokuwiki/lib/plugins/config/core/Setting/SettingSavedir.php
/dokuwiki/lib/plugins/config/core/Setting/SettingString.php
/dokuwiki/lib/plugins/config/lang/cs/lang.php
/dokuwiki/lib/plugins/config/lang/en/lang.php
/dokuwiki/lib/plugins/config/lang/fr/lang.php
/dokuwiki/lib/plugins/config/lang/pl/lang.php
/dokuwiki/lib/plugins/config/settings/config.metadata.php
/dokuwiki/lib/plugins/extension/Extension.php
/dokuwiki/lib/plugins/extension/_test/ExtensionTest.php
/dokuwiki/lib/plugins/extension/_test/testdata/evilbase/plugin.info.txt
/dokuwiki/lib/plugins/popularity/admin.php
/dokuwiki/lib/plugins/revert/admin.php
/dokuwiki/lib/plugins/usermanager/lang/cs/lang.php
/dokuwiki/lib/scripts/locktimer.js
/dokuwiki/lib/scripts/media.js
/dokuwiki/vendor/composer/installed.json
/dokuwiki/vendor/composer/installed.php
/dokuwiki/vendor/phpseclib/phpseclib/README.md
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/DES.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PrivateKey.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PublicKey.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/File/X509.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php
/dokuwiki/vendor/splitbrain/php-archive/src/Zip.php
2cda016617-Jun-2026 Andreas Gohr <gohr@cosmocode.de>

Indexer: signal nothing-to-do via boolean return instead of void

The TaskRunner runs indexing, sitemap, digest and changelog-trim tasks
in sequence and relies on each task returning false when it di

Indexer: signal nothing-to-do via boolean return instead of void

The TaskRunner runs indexing, sitemap, digest and changelog-trim tasks
in sequence and relies on each task returning false when it did no work
so the next one is tried. The indexer rewrite changed addPage(),
deletePage() and renamePage() to return void and only abort via
exceptions, breaking that contract: indexing always looked like work was
done and the following tasks never ran.

Restore the boolean return on these three methods (true when work was
done, false when there was nothing to do) while still using exceptions
to signal errors, and propagate it through TaskRunner::runIndexer().
runIndexer() also no longer forces reindexing on every call.

The legacy compatibility layer is adjusted to match: LegacyIndexer and
idx_addPage() forward the boolean, mapping SearchExceptions back to the
historic error-message/false returns. LegacyIndexer::renamePage()
restores the 'page is not in index' message that the move plugin expects.

Closes #4661

show more ...

79dae64d17-Jun-2026 Andreas Gohr <gohr@cosmocode.de>

Indexer: treat same-second save and index as up to date

needsIndexing() compared the .indexed tag mtime against the page mtime
with <=, so a page that was saved and indexed within the same second wa

Indexer: treat same-second save and index as up to date

needsIndexing() compared the .indexed tag mtime against the page mtime
with <=, so a page that was saved and indexed within the same second was
always reported as still needing indexing. Require the page to be
strictly newer than the index tag instead, so an equal mtime correctly
counts as up to date.

show more ...

2ff7e61c10-Jun-2026 Andreas Gohr <gohr@cosmocode.de>

fix(indexer): explicitly handle renames

In an attempt to simplify the index handling, the newly refactored
indexer implemented a rename as delete+add sequence.

This had unintended consequences for

fix(indexer): explicitly handle renames

In an attempt to simplify the index handling, the newly refactored
indexer implemented a rename as delete+add sequence.

This had unintended consequences for the move plugin which may move
several pages at once, requiring a working index even while some pages
have already been moved while others still remain at their old location.

Related to #4646

show more ...

6e39b4e328-May-2026 Andreas Gohr <andi@splitbrain.org>

refactor(search): extract LegacyIndexer wrapper for BC contract

Move the deprecated helpers (lookupKey, addMetaKeys, renameMetaValue,
getPID, lookup) off Indexer and into a new LegacyIndexer wrapper

refactor(search): extract LegacyIndexer wrapper for BC contract

Move the deprecated helpers (lookupKey, addMetaKeys, renameMetaValue,
getPID, lookup) off Indexer and into a new LegacyIndexer wrapper. The
wrapper also restores the Doku_Indexer return contract (true|string)
around addPage/deletePage/renamePage/clear so plugins using the legacy
API keep working without try/catch.

idx_get_indexer() now returns the LegacyIndexer; getPages stays on
Indexer because plugins call it directly on Indexer instances.

fixes #4645

show more ...

53307a6b09-May-2026 Andreas Gohr <andi@splitbrain.org>

Delete inc/Search/concept.txt

The contents have been added to the wiki

8788dbbd06-May-2026 splitbrain <86426+splitbrain@users.noreply.github.com>

�� Rector and PHPCS fixes


/dokuwiki/_test/README
/dokuwiki/_test/bootstrap.php
/dokuwiki/_test/composer.lock
/dokuwiki/_test/data/media/wiki/exif-orient-6.jpg
/dokuwiki/_test/phpcs.xml
/dokuwiki/_test/rector.php
/dokuwiki/_test/tests/Feed/FeedCreatorOptionsTest.php
/dokuwiki/_test/tests/File/MediaFileTest.php
/dokuwiki/_test/tests/Parsing/HandlerTest.php
/dokuwiki/_test/tests/Parsing/Lexer/LexerTest.php
/dokuwiki/_test/tests/Parsing/Lexer/ParallelRegexTest.php
/dokuwiki/_test/tests/Parsing/Lexer/RecordingHandler.php
/dokuwiki/_test/tests/Parsing/Lexer/StateStackTest.php
/dokuwiki/_test/tests/Parsing/ModeRegistryTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/CodeTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/EolTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/FileTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/FootnoteTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/FormattingTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/HeadersTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/I18nTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/LinksTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/ListsTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/MediaTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/NocacheTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/NotocTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/ParserTestBase.php
/dokuwiki/_test/tests/Parsing/ParserMode/PreformattedTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/QuoteTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/QuotesTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/ReplacementsTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/RssTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/TableTest.php
/dokuwiki/_test/tests/Parsing/ParserMode/UnformattedTest.php
/dokuwiki/_test/tests/Ui/Media/DisplayTest.php
/dokuwiki/_test/tests/inc/IpTest.php
/dokuwiki/_test/tests/inc/changelog_getrelativerevision.test.php
/dokuwiki/_test/tests/inc/common_clientip.test.php
/dokuwiki/_test/tests/inc/common_saveWikiText.test.php
/dokuwiki/_test/tests/lib/exe/fetch_imagetoken.test.php
/dokuwiki/bin/gittool.php
/dokuwiki/bin/indexer.php
/dokuwiki/composer.json
/dokuwiki/composer.lock
/dokuwiki/conf/dokuwiki.php
/dokuwiki/data/deleted.files
/dokuwiki/feed.php
/dokuwiki/inc/Action/Preview.php
/dokuwiki/inc/Action/Search.php
/dokuwiki/inc/Ajax.php
/dokuwiki/inc/Cache/CacheParser.php
/dokuwiki/inc/ChangeLog/ChangeLog.php
/dokuwiki/inc/ChangeLog/MediaChangeLog.php
/dokuwiki/inc/ChangeLog/PageChangeLog.php
/dokuwiki/inc/ChangeLog/RevisionInfo.php
/dokuwiki/inc/ErrorHandler.php
/dokuwiki/inc/Extension/SyntaxPlugin.php
/dokuwiki/inc/Feed/FeedCreator.php
/dokuwiki/inc/Feed/FeedCreatorOptions.php
/dokuwiki/inc/File/MediaFile.php
/dokuwiki/inc/File/PageFile.php
/dokuwiki/inc/Ip.php
/dokuwiki/inc/Ip32.php
/dokuwiki/inc/Manifest.php
/dokuwiki/inc/Parsing/Handler.php
/dokuwiki/inc/Parsing/Handler/AbstractRewriter.php
/dokuwiki/inc/Parsing/Handler/CallWriter.php
/dokuwiki/inc/Parsing/Handler/Lists.php
/dokuwiki/inc/Parsing/Handler/Nest.php
/dokuwiki/inc/Parsing/Handler/Preformatted.php
/dokuwiki/inc/Parsing/Handler/Quote.php
/dokuwiki/inc/Parsing/Handler/Table.php
/dokuwiki/inc/Parsing/Lexer/Lexer.php
/dokuwiki/inc/Parsing/Lexer/ParallelRegex.php
/dokuwiki/inc/Parsing/ModeRegistry.php
/dokuwiki/inc/Parsing/Parser.php
/dokuwiki/inc/Parsing/ParserMode/AbstractFormatting.php
/dokuwiki/inc/Parsing/ParserMode/Acronym.php
/dokuwiki/inc/Parsing/ParserMode/Base.php
/dokuwiki/inc/Parsing/ParserMode/Camelcaselink.php
/dokuwiki/inc/Parsing/ParserMode/Code.php
/dokuwiki/inc/Parsing/ParserMode/Deleted.php
/dokuwiki/inc/Parsing/ParserMode/Emaillink.php
/dokuwiki/inc/Parsing/ParserMode/Emphasis.php
/dokuwiki/inc/Parsing/ParserMode/Entity.php
/dokuwiki/inc/Parsing/ParserMode/Eol.php
/dokuwiki/inc/Parsing/ParserMode/Externallink.php
/dokuwiki/inc/Parsing/ParserMode/File.php
/dokuwiki/inc/Parsing/ParserMode/Filelink.php
/dokuwiki/inc/Parsing/ParserMode/Footnote.php
/dokuwiki/inc/Parsing/ParserMode/Header.php
/dokuwiki/inc/Parsing/ParserMode/Hr.php
/dokuwiki/inc/Parsing/ParserMode/Internallink.php
/dokuwiki/inc/Parsing/ParserMode/Linebreak.php
/dokuwiki/inc/Parsing/ParserMode/Listblock.php
/dokuwiki/inc/Parsing/ParserMode/Media.php
/dokuwiki/inc/Parsing/ParserMode/ModeInterface.php
/dokuwiki/inc/Parsing/ParserMode/Monospace.php
/dokuwiki/inc/Parsing/ParserMode/Multiplyentity.php
/dokuwiki/inc/Parsing/ParserMode/Nocache.php
/dokuwiki/inc/Parsing/ParserMode/Notoc.php
/dokuwiki/inc/Parsing/ParserMode/Preformatted.php
/dokuwiki/inc/Parsing/ParserMode/Quote.php
/dokuwiki/inc/Parsing/ParserMode/Quotes.php
/dokuwiki/inc/Parsing/ParserMode/Rss.php
/dokuwiki/inc/Parsing/ParserMode/Smiley.php
/dokuwiki/inc/Parsing/ParserMode/Strong.php
/dokuwiki/inc/Parsing/ParserMode/Subscript.php
/dokuwiki/inc/Parsing/ParserMode/Superscript.php
/dokuwiki/inc/Parsing/ParserMode/Table.php
/dokuwiki/inc/Parsing/ParserMode/Underline.php
/dokuwiki/inc/Parsing/ParserMode/Unformatted.php
/dokuwiki/inc/Parsing/ParserMode/Windowssharelink.php
/dokuwiki/inc/Parsing/ParserMode/Wordblock.php
/dokuwiki/inc/PassHash.php
/dokuwiki/inc/Remote/ApiCore.php
FulltextSearch.php
/dokuwiki/inc/Sitemap/Mapper.php
/dokuwiki/inc/Subscriptions/BulkSubscriptionSender.php
/dokuwiki/inc/TaskRunner.php
/dokuwiki/inc/Ui/Backlinks.php
/dokuwiki/inc/Ui/Media/Display.php
/dokuwiki/inc/Ui/MediaDiff.php
/dokuwiki/inc/Ui/MediaRevisions.php
/dokuwiki/inc/Ui/PageRevisions.php
/dokuwiki/inc/Ui/Search.php
/dokuwiki/inc/Ui/SearchState.php
/dokuwiki/inc/common.php
/dokuwiki/inc/deprecated.php
/dokuwiki/inc/html.php
/dokuwiki/inc/infoutils.php
/dokuwiki/inc/io.php
/dokuwiki/inc/lang/de-informal/lang.php
/dokuwiki/inc/lang/de/lang.php
/dokuwiki/inc/lang/en/lang.php
/dokuwiki/inc/lang/fr/lang.php
/dokuwiki/inc/lang/pl/lang.php
/dokuwiki/inc/lang/ru/lang.php
/dokuwiki/inc/lang/tr/lang.php
/dokuwiki/inc/lang/tr/onceexisted.txt
/dokuwiki/inc/legacy.php
/dokuwiki/inc/load.php
/dokuwiki/inc/media.php
/dokuwiki/inc/parserutils.php
/dokuwiki/inc/search.php
/dokuwiki/inc/template.php
/dokuwiki/lib/exe/fetch.php
/dokuwiki/lib/images/larger.svg
/dokuwiki/lib/images/smaller.svg
/dokuwiki/lib/images/wrap.svg
/dokuwiki/lib/plugins/authldap/lang/tr/settings.php
/dokuwiki/lib/plugins/authpdo/lang/tr/lang.php
/dokuwiki/lib/plugins/authplain/lang/tr/lang.php
/dokuwiki/lib/plugins/config/lang/cs/lang.php
/dokuwiki/lib/plugins/config/lang/de/lang.php
/dokuwiki/lib/plugins/config/lang/en/lang.php
/dokuwiki/lib/plugins/config/lang/es/lang.php
/dokuwiki/lib/plugins/config/lang/fr/lang.php
/dokuwiki/lib/plugins/config/lang/hu/lang.php
/dokuwiki/lib/plugins/config/lang/it/lang.php
/dokuwiki/lib/plugins/config/lang/pl/lang.php
/dokuwiki/lib/plugins/config/lang/pt/lang.php
/dokuwiki/lib/plugins/config/lang/tr/lang.php
/dokuwiki/lib/plugins/config/settings/config.metadata.php
/dokuwiki/lib/plugins/extension/Extension.php
/dokuwiki/lib/plugins/extension/lang/tr/lang.php
/dokuwiki/lib/plugins/info/syntax.php
/dokuwiki/lib/plugins/logviewer/style.less
/dokuwiki/lib/plugins/usermanager/lang/ru/lang.php
/dokuwiki/lib/scripts/editor.js
/dokuwiki/lib/scripts/page.js
/dokuwiki/lib/scripts/toolbar.js
/dokuwiki/lib/styles/screen.css
/dokuwiki/lib/tpl/dokuwiki/css/content.less
/dokuwiki/lib/tpl/dokuwiki/css/pagetools.less
/dokuwiki/vendor/composer/installed.json
/dokuwiki/vendor/composer/installed.php
/dokuwiki/vendor/kissifrot/php-ixr/src/Message/Message.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Common/Functions/Strings.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/ChaCha20.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/OpenSSH.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/SymmetricKey.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/DES.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/DH.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PrivateKey.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PublicKey.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve25519.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve448.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/Common.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPrivate.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PrivateKey.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PrivateKey.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PublicKey.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/Salsa20.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/File/X509.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php
/dokuwiki/vendor/phpseclib/phpseclib/phpseclib/openssl.cnf
/dokuwiki/vendor/splitbrain/slika/README.md
/dokuwiki/vendor/splitbrain/slika/src/GdAdapter.php
/dokuwiki/vendor/splitbrain/slika/src/ImageInfo.php
4f29a5b906-May-2026 Andreas Gohr <andi@splitbrain.org>

SearchIndex: fix comment position

single line comment moved to the wrong line on reformatting

06053dca10-Apr-2026 Andreas Gohr <andi@splitbrain.org>

SearchIndex: remove write side effect from retrieveRow()

retrieveRow() padded the index file when the requested RID was beyond
the current length. This was an optimization for subsequent changeRow()

SearchIndex: remove write side effect from retrieveRow()

retrieveRow() padded the index file when the requested RID was beyond
the current length. This was an optimization for subsequent changeRow()
calls, but changeRow() already handles padding on its own. The side
effect was also inconsistent with retrieveRows() which is a pure read.

Added a cross-index integration test verifying RID consistency across
entity, token, frequency and reverse indexes when multiple entities
share tokens.

show more ...

5d034a7508-Apr-2026 Andreas Gohr <andi@splitbrain.org>

SearchIndex: increase index version

9369b4a908-Apr-2026 Andreas Gohr <andi@splitbrain.org>

SearchIndex: rector, phpcs, type hint fixes

db8be58608-Apr-2026 Andreas Gohr <andi@splitbrain.org>

SearchIndex: review fixes — auto-save MemoryIndex, cast TupleOps counts, style cleanups

- MemoryIndex: auto-save dirty data on unlock/destruction to prevent
silent index corruption when indexes ar

SearchIndex: review fixes — auto-save MemoryIndex, cast TupleOps counts, style cleanups

- MemoryIndex: auto-save dirty data on unlock/destruction to prevent
silent index corruption when indexes are used in tandem
- TupleOps::parseTuples(): cast exploded count strings to int
- FileIndex::retrieveRow(): document the write-on-read padding behavior
- Fix whitespace issues in ApiCore, common.php, Sitemap/Mapper
- Update concept.txt to reflect MemoryIndex auto-save behavior

show more ...

2a22d4b908-Apr-2026 Andreas Gohr <andi@splitbrain.org>

SearchIndex: document Tokenizer::isValidSearchTerm() in concept.txt

1148921d08-Apr-2026 Andreas Gohr <andi@splitbrain.org>

SearchIndex: unify CollectionSearch API and optimize search pipeline

- Remove separate lookup() API from CollectionSearch. All searches now
use addTerm()/execute() with a single unified pipeline.

SearchIndex: unify CollectionSearch API and optimize search pipeline

- Remove separate lookup() API from CollectionSearch. All searches now
use addTerm()/execute() with a single unified pipeline.
- Add matches() predicate to Term using efficient string functions
(===, str_starts_with, str_ends_with, str_contains) instead of regex.
- Add caseInsensitive() support on CollectionSearch and Term for
metadata/title searches where indexed values preserve case.
- Remove callback support from MetadataSearch::lookupKey() — the only
real usage (case-insensitive substring) is replaced by
caseInsensitive() + wildcards.
- Remove min-length validation from Term. Add Tokenizer::isValidSearchTerm()
for callers that need it (FulltextSearch, Indexer::lookup).
- Optimize execute() from 4 group passes to 2: scan tokens + resolve
frequencies in one pass per group, batch entity name resolution, then
populate Terms.
- Store full match detail in Term: entity → token → frequency. New
accessors getMatches(), getEntityTokens(), getEntityFrequencies()
derive different views from this single data structure.
- Term no longer used as scratch pad by CollectionSearch. Index-internal
data (token IDs, entity IDs) stays local to execute(). Terms receive
only final resolved results.
- Use title from search results in MetadataSearch::pageLookupCallBack()
instead of re-fetching via p_get_first_heading().
- Update concept.txt documentation.

show more ...

b9d7a61507-Apr-2026 Andreas Gohr <andi@splitbrain.org>

SearchIndex: updated documentation

to be moved into the wiki later

123456