=== WDD Custom Code Manager ===
Contributors: nasibulalam
Author URI: https://webdevdoer.com/about-nasibul-alam/
Plugin URI: https://webdevdoer.com
Tags: custom css, custom javascript, code snippets, header footer code, custom php
Requires at least: 5.8
Tested up to: 6.8
Requires PHP: 7.4
Stable tag: 1.1.0
License: GPL-2.0+
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Inject custom CSS, JavaScript, HTML and PHP into any page — site-wide or per page — with device targeting, priority control and full export/import.

== Description ==

WDD Custom Code Manager adds custom code to your site without touching theme
files, so nothing is lost when your theme updates.

* **Six code types** — CSS, JavaScript, HTML (head, body or footer) and PHP.
* **Syntax-highlighted editor** using WordPress's bundled CodeMirror.
* **Global or per-page scope** — apply a snippet site-wide, or pick specific
  posts and pages.
* **Device targeting** — show code on desktop, tablet or mobile only, with
  breakpoints you control. CSS is wrapped in media queries; JavaScript is
  wrapped in width guards.
* **Priority control** — order your snippets, and load them after all other
  theme and plugin code so yours wins.
* **Instant cache purging** — saving a snippet clears your page cache
  automatically, so changes appear right away.
* **Export and import** — move snippets between sites as JSON.

= Load order and priority =

With **Force Highest Priority** enabled (the default), the plugin buffers the
page and writes your CSS immediately before `</head>` and your JavaScript
immediately before `</body>` — after every theme and plugin hook has already
run. Your CSS therefore wins the cascade against any rule of equal specificity,
and your JavaScript runs last.

If another plugin conflicts with page buffering, switch the setting off and the
plugin falls back to standard `wp_head` / `wp_footer` output at the highest hook
priority.

= Caching =

Saving, toggling, deleting or importing a snippet purges every caching layer the
plugin can detect: WP Rocket, LiteSpeed Cache, W3 Total Cache, WP Super Cache,
WP Fastest Cache, Autoptimize, SiteGround Optimizer, Cache Enabler, Breeze,
WP-Optimize, Hummingbird, Swift Performance, Nginx Helper, Kinsta, WP Engine,
Pantheon, Cloudflare, Varnish and Elementor.

The Settings screen lists which layers were detected on your install, and a
**Purge Code Cache** item is added to the admin bar.

= PHP snippets =

PHP snippets are **disabled by default** and must be switched on in Settings.
They are executed server-side with `eval()`, so only enable this if you fully
trust and review every snippet you save. Access is restricted to users with the
`manage_options` capability.

== Installation ==

1. Upload the `wdd-custom-code-manager` folder to `/wp-content/plugins/`, or
   install the ZIP through **Plugins → Add New → Upload Plugin**.
2. Activate the plugin through the **Plugins** screen.
3. Go to **Code Manager → Add New** to create your first snippet.

== Frequently Asked Questions ==

= My snippet changes aren't showing up on the frontend. =

Check that **Auto-purge caches on save** is enabled under **Code Manager →
Settings**, and that the Settings screen lists your caching plugin under
"Detected caching layers". If your cache or CDN isn't listed, purge it once
manually, then use the **Purge Code Cache** item in the admin bar after future
edits.

If you are behind a CDN or reverse proxy the plugin can't reach, hook your own
purge onto the `wdd_ccm_purge_page_caches` action.

= My CSS is being overridden by the theme. =

Make sure **Force Highest Priority** is enabled in Settings. That places your
CSS last in `<head>`, so it beats any theme or plugin rule of equal
specificity. If a theme rule is more specific than yours, you still need a
more specific selector — load order cannot beat higher specificity.

= Will my snippets survive a theme change? =

Yes. Snippets are stored in their own database table, independent of the active
theme.

= Are snippets removed when I uninstall the plugin? =

Deleting the plugin drops its database table and removes its options. Deactivating
it leaves your snippets intact.

== Screenshots ==

1. The snippets list, showing code type, scope, device targeting and status.
2. The snippet editor with syntax highlighting and targeting options.
3. The settings screen, including priority and cache controls.

== Upgrade Notice ==

= 1.1.0 =
Fixes HTML Body snippets being output twice, and adds automatic page-cache
purging so edits appear immediately. Snippet CSS and JavaScript now load after
all other theme and plugin code. Includes a database schema upgrade that runs
on the first page load after updating — take a backup first.

== Changelog ==

= 1.1.0 =

Priority and cache-invalidation release.

**Fixed**

* HTML Body snippets were output twice. The body-injection fallback gated on
  `current_theme_supports( 'body-open' )`, which is not a WordPress feature flag
  and so was always false — the output buffer always ran *and* `wp_body_open`
  also fired on modern themes.
* Saved changes did not appear on the frontend. The plugin performed no cache
  invalidation, so page caches kept serving pre-edit HTML.
* Snippet output could be beaten on load order. Hooks ran at `wp_head` 99 and
  `wp_footer` 99–101, so plugins hooking at 100 or later landed afterwards.
* The database schema never upgraded. `dbDelta()` ran only on activation, which
  does not fire when a plugin is updated in place.
* Contradictory device breakpoints were accepted, producing media queries and JS
  width guards that disagreed with each other.
* Snippets sharing a priority could render in a different order per request.

**Added**

* Force Highest Priority setting (default on) — buffers the page and writes CSS
  before `</head>` and JavaScript before `</body>`, after every hook has run.
* Auto-purge caches on save (default on) — supports 19 caching layers.
* Bypass cache for administrators (default on) — no-cache headers and
  `DONOTCACHEPAGE` on frontend views for administrators.
* Purge Code Cache in the admin bar, and a Purge Now button in Settings that
  lists the detected caching layers.
* Versioned snippet cache, removing the per-request database query from the
  frontend path.
* Per-snippet try/catch around each JavaScript snippet, so one failure no longer
  stops the rest; errors are logged to the browser console with the snippet ID.
* PHP snippet failures are written to `error_log()` when `WP_DEBUG` is enabled.
* Composite database index on `(status, code_type, priority)`.
* Filters: `wdd_ccm_css_output`, `wdd_ccm_js_output`, `wdd_ccm_html_output`,
  `wdd_ccm_render_snippet`, `wdd_ccm_should_buffer`, `wdd_ccm_purge_page_caches`
  and the `wdd_ccm_cache_flushed` action.

**Changed**

* Output now uses two explicit, mutually exclusive modes (buffer and hook) with
  a per-type claim guard, so they can never duplicate each other.
* PHP snippets still execute on `wp_footer`, since they may register hooks or
  enqueue assets.
* A literal `</script` inside a JavaScript snippet is escaped so it cannot close
  the output block early.
* Importing purges caches once on completion rather than once per row.
* Deactivation clears cached snippet output.
* `uninstall.php` also removes the cache-version option and leftover transients.

= 1.0.0 =

* Initial release.
* Custom CSS, JavaScript, HTML (head, body, footer) and PHP snippets.
* Syntax-highlighted editor using WordPress's bundled CodeMirror.
* Global or per-page scope with post and page search.
* Device targeting with configurable breakpoints.
* Per-snippet priority ordering and active/inactive status.
* Bulk activate, deactivate and delete.
* Optional PHP execution, disabled by default.
* JSON export and import, in merge or replace mode.
