New language constants in all six admin language files support the features introduced in the search admin redesign, the admins-panel CRUD rewrite and the database module hardening committed in this session.
Core changes:
- All admin lang files (admin/lang/{de,en,fr,pl,ru,uk}.php):
_DB_MODE, _DB_BLOCKS, _DB_ERRORS, _DB_STOP, _DB_SQL, _DB_PARSE, _DB_PARSEMODE, _DB_RUNMODE — database module UI labels
_SEARCHCLEAR, _SEARCHCLEARINFO, _SEARCHEMPTY, _SEARCHBYMOD, _SEARCHBYDAY, _SEARCHLAST, _SEARCHTOP, _SEARCHTOPMOD, _SEARCHTOTAL, _SEARCHUNIQUE — search statistics management
- _TOKENMISS — CSRF mismatch error message
_ADMINPASSKEEP, _ADMINSELFDEL, _ADMINSELFSUPER, _ADMINLASTSUPER — admin self-protection guard messages
_SEARCHAUTO, _SEARCHAUTOINFO, _SEARCHAUTODONE, _SEARCHENABLED, _SEARCHREADY, _SEARCHINVALID, _SEARCHTYPE, _SEARCHFIELDS, _SEARCHEDIT, _SEARCHREASON, _SEARCHSPECIAL, _SEARCHSIMPLE, _SEARCHNOTABLE, _SEARCHMISSCOLS, _SEARCHNOFIELDS, _SEARCHADDSEL, _SEARCHADDALL — search audit tab labels
- Frontend lang (lang/ru.php):
- _SEARCHLETMIN — minimum search length notice for users
- Changelog admin lang (modules/changelog/admin/lang/fr.php):
_CHLOG_ERR_GH_API: replaced double-quoted string with single-quoted to use consistent quote style
Benefits: - All new admin UI strings are fully translated in all supported languages - Consistent quote style in changelog FR lang file
Technical notes: - Constants follow existing _SEARCH / _ADMIN / DB* naming conventions
A set of targeted fixes eliminating PHP 8.x warnings and potential null-dereference errors caused by missing isset/is_user/type-cast guards.
Core changes:
- core/user.php — getFavorBtn():
- Parameter type changed to ?int, explicit (int) cast applied
- Guard $fid > 0 prevents DB query with id = 0
- $content initialized to '' before conditional blocks — no "undefined" return
- modules/forum/index.php — quickreply():
- Parameters typed ?int|?string; explicit (int) cast applied
- Guard $id > 0 && $catid > 0 prevents rendering form for invalid thread
- modules/help/index.php — help():
$uid now resolved via is_user() ? intval($user[0]) : 0 instead of blind intval($user[0]) when user may not be logged in
- modules/main/index.php — main():
Table aliases added to WHERE/ORDER: s.time, s.status instead of bare names to resolve ambiguity in JOIN queries against news and files tables
- modules/shop/admin/index.php — partnersdetails():
- $a and $partsumges initialized to 0 before use
- Indentation corrected (stray extra indent on $paid assignment)
Benefits: - Eliminates PHP 8 undefined variable and null-coercion warnings in production - Prevents database queries with id = 0 that return unexpected rows
Technical notes: - No behaviour change for valid input; only edge-case guards added
Replaces bare file() calls with is_file()/is_readable() guards throughout the statistics and visit-counter code paths, eliminating PHP warnings on missing or unreadable log files and ensuring correct empty-array fallbacks.
Core changes:
- Core admin statistics (core/admin.php — getStatistic()):
- All file(COUNTER_DIR/...) calls now guarded with is_file() && is_readable()
- Returns [] instead of false on missing log, preventing array_merge errors
- categories.description → intro in ajax_cat() query (column rename follow-up)
- voting query updated: language → lang column (column rename follow-up)
- ajax_cat() edit link corrected to name=categories&op=edit&cid=
- System counter (core/system.php — visit counter closure):
- Extracted $safeReadLines closure with set_error_handler() + try/finally
- Replaces direct file() on statistic.log and ips.log
- Follows the no-@ rule: uses set_error_handler() instead of @ suppression
- Admin statistic module (admin/modules/statistic.php):
- is_file() && is_readable() guards before every file() call on log files
- $daysLog / $statLog variables extracted to avoid repeated string literals
Benefits: - No PHP warnings/notices when counter log files are absent or locked - Complies with project rule: set_error_handler() instead of @ suppression - Consistent behaviour: missing file → empty array, not false
Technical notes: - No changes to log file format or counter logic - set_error_handler() scope is limited by the closure + restore_error_handler()
Both admin/modules/admins.php and admin/modules/database.php receive proper CSRF protection and hardened input handling; the admins module is fully rewritten to enforce self-delete and last-superuser guards.
Core changes:
- Admins module (admin/modules/admins.php):
- getAdmintoken() / checkAdmintoken() — session-bound CSRF token
- getAdminself() — resolves the currently logged-in admin ID
- getAdminmods() / filterAdminmods() — validated module permission list
- getAdminrow() / checkAdminlast() — DB helpers with prepared statements
- adlist(): replaces admins() — POST-form delete with hidden token field
- adform(): replaces add() — splits GET (load) / POST (defaults) clearly
adsave(): full validation including self-delete and last-superuser guards returning human-readable stop messages via _ADMINSELFDEL etc.
- addelete(): CSRF-checked, blocks self and last superuser
- Database module (admin/modules/database.php):
- getDbtoken() / checkDbtoken() — sitekey-based CSRF token
- addDblog() — timestamped append to storage/logs/database_migration.log
getSqlbatch() — robust SQL batch splitter: handles DELIMITER, line/block comments, string literals (single, double, backtick), and escape sequences
- Existing install/sync/delete actions now validate token before execution
Benefits: - Eliminates CSRF attack surface on all destructive admin operations - Self-protection guards prevent accidental lockout of the last superuser - SQL batch parser handles edge cases that explode(';') would miss
Technical notes: - Token uses hash_equals() for timing-safe comparison - getAdmintoken() is session-scoped (invalidated on logout) - getDbtoken() is sitekey-scoped (stable across requests, simpler UX)
Replaces the minimal search admin with a full-featured interface: module compatibility audit, statistics management, and CSRF-protected config saves. The frontend search engine is also refactored for clarity and correct handling of the new per-module config fields.
Core changes:
- Search admin (modules/search/admin/index.php):
- CSRF token pair getSearchtoken() / checkSearchtoken() for all writes
getSearchaudit(): scans active modules, classifies each as special, auto-compatible (has id+title+searchable field) or invalid with reason
- getSearchready() / getSearchenabled() / getSearchinvalid() filters
- Auto-add action: enables all compatible modules in one click
- Statistics tab: top queries, unique count, clear-by-module and by-age
- getSearchcols(): queries information_schema for live column lists
- Search frontend (modules/search/index.php):
- Extracted getSearchMods(), getSearchState(), getSearchModList()
- getSearchStat(): saves query to search_stat table with dedup
- Unified search dispatcher reads anum/anump from config
- Search config (config/search.php):
- New keys: anum (results per page), anump (pagination links)
- Updated default mods list to match renamed/removed modules
- Docs (modules/search/admin/info/ru.md):
- Describes new audit tab, auto-add, statistics management
Benefits: - Admins can see at a glance which modules are searchable and why not - CSRF protection prevents unauthorized config changes - Statistics cleanup prevents unbounded growth of search_stat table
Technical notes: - getSearchspec() encodes hand-crafted mappings for modules with non-standard table/field layout (auto_links, forum, media, shop) - Compatible with existing search_stat table schema
Continues the column-unification effort (Batch W) by renaming legacy column references in the modules and installation schema that were missed in the previous batches.
Core changes:
- SQL schema (setup/sql/table.sql):
- content._text → body, message.content → body, newsletter.content → body
- privat.content → body, voting.questions → body
- Comments admin (admin/modules/comments.php):
- SELECT comment → body, UPDATE SET comment → body
- Account module (modules/account/index.php):
- SELECT comment → body in user activity listing
- Clients admin (modules/clients/admin/index.php):
- infotext → body, prod_id → pid in SELECT / INSERT / UPDATE
- Forum admin (modules/forum/admin/index.php):
- categories.description → intro in category listing query
Benefits: - SQL schema is now consistent with the renamed columns in production tables - All module queries reference the unified column names - Eliminates divergence between install schema and live database structure
Technical notes: - Pure column-name substitution — no logic or behaviour changes - Matches renames applied to core and other modules in Batches M–W
Completes the directory rename started in the previous commit by deleting all obsolete language/ subdirectories across core, admin, modules, setup and templates, and updating every consumer that still referenced the old path.
Core changes:
Directory cleanup (admin/language/, language/, modules/*/language/, modules//admin/language/, setup/language/, templates//images/language/):
- Remove 1064 obsolete files (.htaccess, index.html, .php, .png)
Path references (robots.txt, templates/admin/index.php, templates/lite/index.php):
- Disallow /lang/ instead of /language/ in robots.txt
- scandir() and img_find() calls updated to lang/ and lang/*_mini.png
Test suite (tests/LanguageConstantsUsageTest.php, tests/LanguageValidationTest.php, tests/ModuleStructureTest.php):
- Regex patterns and directory scan paths updated to lang/
Benefits: - Eliminates dead files left behind by the rename commit - Robots.txt and templates correctly reflect new directory layout - Test suite validates lang/ structure instead of the removed language/ dirs
Technical notes: - Pure cleanup — no logic changes, no backward-compat shims needed - All lang/ files were created in the preceding rename commit
All SQL queries, getVar() calls, variable names and HTML form field names updated to match the new column names introduced by Batch W.
Core changes: - modules/content/index.php + admin/: text → body (SELECT, UPDATE, INSERT, getVar, textarea, PHP vars, RSS cache UPDATE) - admin/modules/messages.php: content → body everywhere (SELECT ×2, UPDATE, INSERT, getVar, textarea, list() destructuring) - admin/modules/newsletter.php: content → body everywhere (SELECT, UPDATE, INSERT, getVar, textarea, preview) - core/user.php: _message content → body (SELECT, loop vars, template pass-through); _privat content → body (SELECT ×2, INSERT named param); _content text → body (RSS getContent SELECT) - core/admin.php: _privat p.content → p.body (SELECT + while list()) - core/system.php: _voting questions → body (getVoting SELECT, loop, form field name body[], JS fallback body%5B%5D); updateNewsletter content → body (SELECT + addMail call) - modules/voting/admin/index.php: questions → body (SELECT, UPDATE, INSERT, getVar, form input name body[], loop variable) - setup/index.php: questions → body in legacy import INSERT - modules/clients/index.php: URL param prod_id= → pid= (cosmetic)
Six tables are normalised to use a consistent body column name instead
of the legacy table-specific names (infotext, prod_id→pid, text, content,
questions). The rencol() stored procedure is fully idempotent, so the
scripts are safe to re-run on already-migrated databases.
Core changes: - batch_migrate.sql: add Batch W (CALL rencol for all six tables) - table_update6_3.sql: add Batch W; update Batch U MODIFYs to new names (body replaces text/content/questions in column type definitions) - table_update6_3_finalize_local.sql: add rencol calls + updated MODIFYs for local-install finalizer path
Tables affected: {prefix}_clients_down infotext → body, prod_id → pid {prefix}_content text → body {prefix}_message content → body {prefix}_newsletter content → body {prefix}_privat content → body {prefix}_voting questions → body
All per-module and global language file directories have been renamed
from language/ to lang/ for consistency with modern PHP conventions
and to align with the new single-source multilingual architecture.
Core changes: - Delete all legacy language/ subdirectories (admin, modules, templates) - Add equivalent lang/ directories with identical file contents - core/access.php, core/security.php: update language path references - admin/modules/config.php, lang.php: update getLangPath() and scandir() - blocks/block-languages.php: update opendir() and img_find() paths - CONTRIBUTING.md, README.md, UPGRADING.md: update docs accordingly - tests/: fix path references in LanguageConstantsUsageTest et al.
Benefits: - Cleaner, shorter directory names throughout the module tree - Consistent naming convention across all 40+ module language bundles





