Последнии сообщения форума
Remove the two static <link> tags for the old CodeMirror 2 distribution from all admin layout templates. Asset injection is now handled by Editor::getAssets() which injects driver CSS/JS only when the relevant editor is active on the page. Update base_fingerprint to reflect the current codebase state.
Core changes:
- Admin layouts (templates/*/layouts/admin.html — 4 files):
- Remove: <link rel="stylesheet" href="plugins/codemirror/lib/codemirror.css">
Remove: <link rel="stylesheet" href="plugins/codemirror/addon/hint/show-hint.css"> * These referenced the old plugins/codemirror/ path (pre-plugin-system) * The new CodeMirror 6 assets live in plugins/editors/codemirror/assets/
- Config fingerprint (config/local.php):
Update base_fingerprint to match the current file state after Editor class, plugins, and admin module changes
Benefits: - Layouts are no longer coupled to a specific editor implementation - Editor assets are injected on-demand; pages without code editors load faster
Technical notes: - The old plugins/codemirror/ directory is a separate cleanup task - Fingerprint change is cosmetic; no runtime effect
Replace getTplCodeEditor() with Editor::getCode() and redaktor()/changeeditor() with Editor::getSelect() across all admin panel modules. Migrate the editor change flow in core/admin.php and admin/index.php to use string plugin keys instead of the legacy numeric redaktor flag.
Core changes:
- Admin entry and core (core/admin.php, admin/index.php):
- changeeditor(): store string plugin key instead of numeric editor value
- Read editor key from conf['editor']['admin'] instead of intval($admin[3])
- Validate key with isValidEditor() before saving to DB
- Config module (admin/modules/config.php):
Replace single redaktor select with two rows: editor_user and editor_admin via Editor::getSelect() for each role
- Save handler reads editor_user/editor_admin and writes conf['editor'] block
- editor_code key preserved from existing conf
- Code editor call sites (7 files → Editor::getCode()):
- admin/modules/blocks.php: block code preview field; mode → lang: 'php'
- admin/modules/database.php: SQL query field; mode → lang: 'sql'
- admin/modules/editor.php: file editor; mode → lang inferred from extension
- admin/modules/security.php: HTTP monitor field; mode → lang: 'text'
- admin/modules/template.php: template file editor; mode → lang: 'html'
- admin/modules/uploads.php: network code field; mode → lang: 'html'
- modules/sitemap/admin/index.php: sitemap XML field; mode → lang: 'xml'
- Content editor call sites (account admin):
- modules/account/admin/index.php: account editor select via Editor::getSelect()
Benefits: - Editor::getCode() normalises lang keys (php, sql, html, css, xml, text) replacing the MIME-type mode strings used by old CodeMirror integration - Editor selection UI is driven by plugin manifests instead of hardcoded options
Technical notes: - getTplCodeEditor() and redaktor() are now unused; removal planned separately - 'height' parameter dropped — sizing is now handled per-driver via CSS - No behavioral changes for end users; rendered widget is identical
Wire the Editor class into the system bootstrap and introduce the conf['editor'] config block that maps roles (user, admin, code) to editor plugin keys.
Core changes:
- System bootstrap (core/system.php):
Add require_once for core/classes/editor.php before Template and Parser * Editor is stateless (no instantiation); loaded once at request start
- Global config (config/global.php):
Add conf['editor'] block with three role keys: * 'user' => 'plain' — default editor for front-end content forms * 'admin' => 'plain' — default editor for admin content forms * 'code' => 'codemirror' — default editor for code/syntax fields
- Replaces the old scalar 'redaktor' key (numeric 0/1 flag)
Benefits: - Role-based editor selection is now config-driven - Three independent keys allow different editors for code vs. content
Technical notes: - Existing 'redaktor' key is preserved for backward compatibility until all callers are migrated (handled in subsequent commit) - Plugin keys correspond to directory names under plugins/editors/
Introduce a plugin-based editor architecture that replaces the hardcoded getTplCodeEditor() / getTplBbEditor() / redaktor() helpers with a unified Editor class backed by interchangeable driver plugins. Each editor plugin lives in plugins/editors/<name>/ and implements ContentDriver or CodeDriver.
Core changes:
- Editor class (core/classes/editor.php):
Editor::getContent(array $data): string — render a content (WYSIWYG) widget * Selects driver by role (admin/user) and optional editor/profile overrides
Editor::getCode(array $data): string — render a code/syntax editor widget * Selects driver by conf['editor']['code'] key (default: codemirror)
Editor::getSelect(string $name, string $value, string $type, string $role): string — render an <select> listing available editor choices for role
Editor::getAssets(string $context): string — collect CSS/JS assets from active drivers for the current request context
- ContentDriver and CodeDriver interfaces define the driver contract
- Plugin manifests (manifest.json) declare name, roles, formats, and profiles
- Editor plugins (plugins/editors/):
- plain/ — plain textarea (no assets); supports content for both roles
codemirror/ — CodeMirror 6 bundle for code editing (cm6.bundle.js + cm6.css) * driver.php implements CodeDriver * build/entry.js, build.mjs: esbuild pipeline source
ckeditor/ — CKEditor 5 bundle for rich content editing (ckeditor.bundle.js) * driver.php implements ContentDriver (admin role, full/simple profiles) * build/entry.js, build.mjs: esbuild pipeline source
tinymce/ — TinyMCE 7 self-hosted distribution (tinymce.min.js + plugins/) * driver.php implements ContentDriver (admin + user roles)
toastui/ — Toast UI Editor (toastui-editor.all.min.js + css) * driver.php implements ContentDriver (user role, markdown profile)
Benefits: - Editor choice is configurable per role (user/admin/code) in conf['editor'] - Adding a new editor requires only a plugin directory + manifest + driver.php - Asset injection is handled by Editor::getAssets() — no hardcoded <link> in layouts
Technical notes: - ContentDriver::getWidget() signature: (id, name, value, profile) - CodeDriver::getWidget() signature: (id, name, value, lang, profile) - Manifests use JSON; driver.php must define a class named <Name>Driver - TinyMCE is vendored in full (self-hosted); no CDN dependency
Add a dedicated test suite for the new Parser class and clean up the obsolete filterMarkdown / filterReplaceText function stubs from AdminPreviewBridgeFlowTest now that the real Parser class is available.
Core changes:
- New test suite (tests/Unit/ParserFixturesTest.php):
- Loads core/classes/parser.php directly via require_once
Defines minimal stub functions (img_find, replace_break, is_user) required by Parser without the full CMS bootstrap
Data-provider test cases covering safe and unsafe mode output, BB-code tags, Markdown blocks, and inline content
- Updated test (tests/Unit/AdminPreviewBridgeFlowTest.php):
Remove filterMarkdown() and filterReplaceText() function stubs * No longer needed: Parser class is loaded directly in the test
- Remove __test_filter_markdown global from setUp()
- Remove associated fixture setup in previewPartialHandlesHtmlContentCorrectly()
Benefits: - Parser class is covered by fixture-based unit tests - AdminPreviewBridgeFlowTest is cleaner without surrogate function stubs
Technical notes: - ParserFixturesTest requires BASE_DIR to be defined; handled by bootstrap - Removing the stubs does not affect existing test assertions — the real Parser produces identical output for the affected test cases
Replace all remaining filterMarkdown() + filterReplaceText() call pairs with $prs->filterContent() across the front-end module controllers and block scripts. Add global $prs where required.
Core changes:
- Block scripts (blocks/):
- block-links.php: 2 description tooltip call sites → $prs->filterContent()
- block-auto_links.php: 1 description tooltip → $prs->filterContent()
- Module front-end controllers (modules/*/index.php):
- account: view() signature field, last() comment snippet (4 sites)
- auto_links: description rendering
- changelog: common.php entry body
- clients, contact: text field rendering
- content: body rendering
- faq: answer body
- files, media: description fields
- forum: post body and reply content (multiple sites)
- help: article body
- jokes: joke body
- links: description fields
- main: block content rendering
- money: invoice and confirmation text fields
- news: article body and intro
- order: order detail rendering
- pages: page body
- shop: product description, body and intro fields
Benefits: - Zero filterMarkdown/filterReplaceText calls remain anywhere in the codebase - All public-facing content rendering uses the unified Parser API
Technical notes: - All changes are mechanical replacements; no logic changes - $prs is already available as a global from system.php bootstrap
Replace filterMarkdown() + filterReplaceText() with $prs->filterContent() in all admin-context module files. Add global $prs to affected function signatures.
Core changes:
- Admin panel modules (admin/modules/):
- admins.php → save(): migrate mail body rendering for admin password email
- security.php → bansave(): migrate ban notification email body
- Module admin controllers (modules/*/admin/index.php):
- account/admin: save() — migrate mail body for new-user password email
- help/admin: view help page text rendering
money/admin: billing() call — migrate author and info text fields (2 sites) + payment notification email body
- order/admin: order confirmation email body
- shop/admin: product preview body_b and body_c fields (2 sites)
Benefits: - All admin module PHP files are free of filterMarkdown/filterReplaceText - Consistent $prs->filterContent() pattern across the entire admin layer
Technical notes: - All changes are mechanical; argument order adjusted to filterContent($src, false, $mod) - No logic or output changes
Replace every filterMarkdown() + filterReplaceText() call pair in the core function files with $prs->filterContent(). Add global $prs to all affected function signatures.
Core changes:
- Admin helpers (core/admin.php):
- getAdminPrivateList(): add global $prs; replace filterMarkdown/filterReplaceText
- getAdminInfo(): add global $prs; replace filterMarkdown/filterReplaceText
- Template helpers (core/helpers.php):
- getTplViewFieldRows(): add global $prs; replace for type-2 custom field values
- getTplPreviewContent(): add global $prs; replace for $bodya and $bodyb
- setTplAdminInfoPage(): add global $prs; replace for $info rendering
- User helpers (core/user.php):
- setMessageShow(): add global $prs; replace for message body
- getUserBlock(): add global $prs; replace for user sidebar block
- updatePost(): add global $prs; replace for inline post rendering (2 sites)
- getPrivateMessageView(): add global $prs; replace for body and sig fields
- view() (account): add global $prs; replace for $seodesc and $sign
- last(): add global $prs; replace for comment snippet truncation
Benefits: - All core PHP functions use the new Parser API; zero legacy calls remain - Global $prs follows the same declaration pattern as $tpl and $db
Technical notes: - Argument order change: filterMarkdown($src, $mod, $safe) becomes $prs->filterContent($src, $safe, $mod) — safe flag is the second arg - No behavioral changes; pipeline logic is identical
Move the Markdown+BB-code processing pipeline out of the inline anonymous class in core/system.php into a dedicated Parser class at core/classes/parser.php. Expose a single entry point filterContent() that merges the old two-step filterMarkdown() + filterReplaceText() call into one method. Instantiate $prs globally alongside $tpl in system.php and remove the now-replaced standalone functions.
Core changes:
- New class (core/classes/parser.php):
Parser class with filterContent(string $src, bool $safe, string $mod) as the unified entry point * safe=true: escapes user-injected HTML and applies URL allowlist * safe=false: allows raw HTML blocks and admin BB tags
Internal pipeline: filterBbBlocks → filterCode → filterBlocks → filterSafe (safe mode) → filterStash
Per-request parse cache keyed by md5(src + safe + mod) to avoid re-parsing identical content within one request
All logic is a direct extraction of the anonymous class from system.php; no behavioral changes
- Bootstrap (core/system.php):
- Add require_once for core/classes/parser.php
- Instantiate $prs = new Parser() immediately after $tpl
- Remove filterMarkdown() and filterReplaceText() function definitions
Migrate all call sites inside system.php to $prs->filterContent() * getBlocks(), scheduler mail, comment rendering, updateComment(),
getUserSessionInfo() area
Benefits: - Parser logic is testable in isolation via core/classes/parser.php - Single filterContent() call replaces every filterMarkdown() + filterReplaceText() pair - Removes 780-line anonymous class from system.php bootstrap
Technical notes: - $prs is a global like $tpl and $db; callers must declare global $prs - filterMarkdown() and filterReplaceText() no longer exist after this commit - All remaining callers are migrated in subsequent commits
Regenerate base_fingerprint to reflect the current state of the codebase after the admin fragment namespace was flattened and all PHP callers were updated to use flat fragment paths.
Core changes:
- Config fingerprint (config/local.php):
Update base_fingerprint from 95db252... to 67064900... * Reflects changes across templates, core, admin modules, and
module admin/public pages from the fragment refactor
Benefits: - Fingerprint is consistent with the actual file state - Prevents false-positive change detection on next build
Technical notes: - No functional change; fingerprint is a build-state checksum only





