=== Fstyle Final Output Replacer ===
Contributors: fstylegear09543
Tags: output buffer, replace, regex, optimization, html cleanup
Requires at least: 6.0
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.3.2
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Dynamically replace, clean up, or optimize the absolute final front-end HTML output text based on database-driven rules.

== Description ==

Fstyle Final Output Replacer hooks into the absolute final stage of WordPress's output buffering to dynamically perform string replacements or regular expression (Regex) matches on the raw front-end HTML before it is sent to the browser.

This plugin is highly useful for cleaning up sensitive HTML comments, injecting custom snippets, correcting dynamically generated URLs, or bulk-patching strings across your entire site without altering core or theme files.

=== Features ===
* **Final Stage Buffering:** Modifies the source text at the very last moment (`shutdown` hook).
* **Plain Text & Regex Support:** Choose between simple string replacement or advanced Regular Expressions (`preg_replace`).
* **Execution Order Management:** Set custom sort orders to determine exactly which replacement rule executes first.
* **Granular Controls:** Easily enable, disable, edit, or delete registered rules with a single click.
* **Developer Friendly:** Escapes and processes tabs (`\t`), newlines (`\n`), and carriage returns (`\r`) properly.
* **HTML Pages Only:** Rules are applied only to front-end HTML pages (`Content-Type: text/html`). REST API (JSON), admin-ajax, cron, feeds, XML sitemaps, robots.txt and the admin area are never changed.
* **Safe Rule Editing:** Regular expressions are tested when you save them, and invalid patterns are rejected with an error message.
* **Secure UI:** Built with WordPress native styling, Nonce protection, and capability checks (`manage_options`, plus `unfiltered_html` to add, edit, enable, disable, sort, or delete rules).

=== Notes on regular expressions ===
* A regex rule is passed to PHP `preg_replace()` as it is. Always enclose the pattern in delimiters, e.g. `/pattern/i` or `#pattern#s`. A pattern without delimiters (such as `foo.*bar`) is rejected.
* Rules run against the whole HTML of every front-end page. A broad pattern (for example `/<div.*>/s`) can remove large parts of your pages. Test new rules on a staging site first, and keep them as specific as possible.
* Rules run in the sort order you set. A later rule sees the output of the earlier rules.
* Very heavy patterns slow down every page. If a pattern fails at runtime (for example, because of the PCRE backtrack limit), the rule is skipped and the page is sent unchanged by that rule.

== Installation ==

1. Upload the entire `fstyle-final-output-replacer` folder to the `/wp-content/plugins/` directory.
2. Activate the plugin through the 'Plugins' menu in WordPress.
3. Navigate to the new **Final Replacer** menu item in your admin dashboard to start managing your replacement rules.

== Frequently Asked Questions ==

= Does this plugin modify the content in the database? =
No. It only alters the final output buffer dynamically in memory right before the page renders on the front-end. Your original database content remains completely untouched.

= Can I use complex regular expressions? =
Yes, you can check the "Regex" option and input standard PHP regex modifiers and delimiters (e.g., `/<meta\s+name=["']?robots["']?[^>]*\/?>/is`). The pattern is tested when you save it, and an invalid pattern is not saved.

= Which responses are changed? =
Only front-end HTML pages. JSON (REST API, admin-ajax), feeds, XML sitemaps, robots.txt, cron requests and the admin area are left untouched.

= Will this plugin work with page caching plugins? =
Usually yes, but replacements occur before the final HTML output is sent.
If a static page cache is already generated, you may need to clear the cache after changing rules.

= I changed a rule, but my pages did not change. Why? =
If you use a page caching plugin (or a server or CDN cache), visitors may still get pages that were cached before the change. After you change rules, including enabling, disabling, or deleting a rule, clear the page cache so that the new rules are used on every page.

= Who can add or edit rules? =
Administrators who have both the `manage_options` and `unfiltered_html` capabilities. A rule can insert any HTML or JavaScript into every page, so users without `unfiltered_html` (for example, site administrators on a multisite network, or sites with `DISALLOW_UNFILTERED_HTML`) cannot add, edit, enable, disable, sort, or delete rules. They can only view the existing rules.

= Is this plugin secure? =
Every data-saving action, activation toggle, and deletion request is validated via WordPress Nonces and User Capability Checks (`manage_options`, and `unfiltered_html` for every change to the rules).

= What happens when I delete the plugin? =
When you delete the plugin from the Plugins screen, its database table and options are removed. Deactivating the plugin keeps your rules.

== Screenshots ==

1. The main administration dashboard where you can easily create, sort, and manage your final HTML replacement rules.

== Changelog ==

= 1.3.2 =
* Fixed: on sites with a persistent object cache (APCu, Redis, ...), rules could be skipped on the front end because a stale cached option made the plugin think its table was not ready.
* Performance: the table check now runs on admin screens only.

= 1.3.1 =
* Fixed: with a persistent object cache (APCu, Redis, ...), new or changed rules could stay unused on the front end. The rule list is now cached only for the current request.

= 1.3.0 =
* Distributed from functions.fs-create.net instead of WordPress.org. Download: https://functions.fs-create.net/downloads/final-output-replacer/
* Added self-hosted updates: new versions appear on the Plugins screen and can be updated with one click (Update URI header).

= 1.2.0 =
* Security: saving rules now requires the `unfiltered_html` capability.
* Security: enabling, disabling, sorting, and deleting rules also require the `unfiltered_html` capability. Without it, the rules can only be viewed.
* Rules are now applied only to front-end HTML pages. REST API, admin-ajax, cron, feeds, XML sitemaps and robots.txt are no longer changed.
* Regular expressions are tested when saved. Invalid patterns and patterns without delimiters are rejected with an error message.
* Performance: the database table is no longer checked with `SHOW TABLES` on every page view. The table version is stored in an option.
* Added `uninstall.php` to remove the table and options when the plugin is deleted.
* The delete confirmation no longer uses an inline `onclick` attribute.
* Admin screen labels are now translatable.
* Class names now use the plugin prefix, and the table name is escaped with `esc_sql()` before it is used in queries.

= 1.1.7 =
* Improved Plugin Check compatibility and security handling.
* Added cache optimization for rule loading.
* Improved admin-side validation and sanitization.

= 1.1.5 =
* Enhanced admin dashboard UI design and polished buttons using native WordPress components.

= 1.1.4 =
* Implemented `wp_unslash` formatting to completely prevent backslash duplication during Regex pattern editing.
* Separated inline action forms to isolate execution sort order updates.

= 1.1.0 =
* Added dynamic migration logic to handle database table schema adjustments safely.

= 1.0.0 =
* Initial release. Secure final output replacement engine with standard Nonce verification.

== Upgrade Notice ==

= 1.3.2 =
Rules now work on sites with a persistent object cache.

= 1.3.1 =
Rules now take effect right away on sites with a persistent object cache.

= 1.3.0 =
From this version, updates are delivered from functions.fs-create.net and shown on the Plugins screen.

= 1.2.0 =
Rules are now applied only to HTML pages, and every change to the rules requires the unfiltered_html capability. Invalid regular expressions can no longer be saved.