=== ALTOS ===
Contributors: ffscz
Tags: performance, admin, optimization, speed, defer
Requires at least: 6.0
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 1.3.9
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Intelligent admin-side loading control — choose which plugins load on which admin screen, with automatic data-driven suggestions.

== Description ==

**ALTOS** speeds up the WordPress admin by giving you per-screen control over which active plugins are actually loaded. Most WordPress sites accumulate dozens of plugins over time, but only a few are needed on any given admin screen. Loading them all on every page wastes memory, time, and database queries.

ALTOS operates at the WordPress core level via the MU-plugins mechanism, intercepting the loading pipeline before WordPress fully initialises. It cleanly skips heavy code paths on screens where they aren't needed — while preserving admin menus, dependency relationships, and safety guards.

**Key features**

* **Per-screen control** — Set rules for each admin screen (Dashboard, Posts, Pages, Settings, WooCommerce, Custom Post Types, …).
* **Three states per rule** — Enabled (always load), Disabled (never load), Defer (load after the main page).
* **Smart menu preservation** — Admin menu entries stay accessible for blocked/deferred items via an automatic snapshot system.
* **Hierarchical rules** — Global → group → screen, with intelligent inheritance.
* **Automatic mode with suggestions** — Confidence-scored recommendations from real performance samples; you review and apply manually.
* **Dependency cascade detection** — Catches dependent items when a parent is blocked.
* **Request-type optimisation** — Separate rules for AJAX, REST API, WP-Cron, and WP-CLI.
* **Update Optimizer** — Three strategies to reduce update-check overhead without breaking badge counts.
* **Per-plugin performance metrics** — Real-time load time, DB queries, memory.
* **Developer tools** — Admin drawer, admin-bar integration, REST endpoints, extensive filters/actions.
* **Built-in translations** — Czech, Slovak, Polish, German, French, Spanish.

**Typical impact**

* 30–50 % faster admin pages.
* 20–40 fewer database queries per admin page.
* 1–5 MB less memory per blocked item.

**Safety by default**

* Manual mode requires explicit rules — nothing is changed without your action.
* Automatic mode only *suggests* — never applies on its own.
* The loader protects itself from being blocked.
* Page-builder bypass for Elementor, Bricks, Divi, Beaver Builder during active editing sessions.
* Emergency recovery URL for one-click bypass if a misconfiguration breaks the admin.

== External Services ==

This plugin does not contact any external services. It does not send analytics, telemetry, license checks, or any other network requests. All rules, samples, snapshots, and configuration are stored exclusively in your own WordPress database.

The "Update Optimizer" feature exclusively *throttles* the standard WordPress update-check HTTP requests to `api.wordpress.org` — it never adds new endpoints and never sends additional data.

== Installation ==

1. Install via **Plugins → Add new → Upload Plugin** in WordPress, or upload the unzipped folder to `/wp-content/plugins/altos/`.
2. Activate the plugin through the **Plugins** screen in WordPress.
3. On activation, the plugin automatically writes a small MU-loader file to `wp-content/mu-plugins/altos.php`. This is what allows per-screen filtering to run before WordPress loads the regular plugins. The file is removed automatically on deactivation.
4. Go to **Settings → Plugin Manager** in your WordPress admin.
5. Configure rules manually, or enable **Automatic mode** to get data-driven suggestions after a day or two of sampling.

**Requirements**

* PHP 7.4 or newer (PHP 8.0+ recommended).
* WordPress 6.0 or newer.
* Write permission for `wp-content/mu-plugins/` (almost all hosts allow this; some managed-WordPress hosts restrict it).

== Frequently Asked Questions ==

= How does this differ from "deactivating" a plugin? =

ALTOS runs **before** WordPress loads regular plugins, using the MU-plugins mechanism. That means the code is genuinely *not loaded* on screens where you don't need it — not loaded-and-then-suppressed. Deactivation is global and permanent; this lets you keep an item active site-wide while skipping it on specific admin screens or request types.

= How does Automatic mode work? =

For 24–48 hours after you enable it, the loader samples real performance data on your own admin: load time, database queries, memory per active item, per admin screen. It then analyses those samples to suggest rules with a confidence score (0–100 %) and estimated savings. **Suggestions are never applied automatically** — you review them and apply with one click.

= Is it safe to block items? =

ALTOS has multiple safeguards:

* Dependency cascade detection — if you block a parent (e.g. WooCommerce), dependents are flagged automatically.
* Smart menu preservation keeps blocked items' admin menu entries reachable.
* Critical scenarios (page-builder editing, WooCommerce checkout/cart) are auto-excluded.
* The loader itself is auto-protected from being blocked.

Recommendation: enable Automatic mode on a staging site first, review the suggestions, then export to production.

= Does this work with page builders? =

Yes. Elementor, Bricks, Divi, and Beaver Builder edit sessions are detected and the loader steps out of the way to avoid breaking editor previews.

= What about WooCommerce? =

Full WooCommerce support: cart, checkout and account pages are excluded from any blocking on the frontend. Admin screens are recognised per area (products, orders, settings, …) so you can keep WooCommerce active on its own screens while skipping it elsewhere.

= Does it affect the frontend? =

The Frontend Optimizer is an opt-in feature. If you leave it disabled (default), the frontend is completely unaffected. With it enabled, you can selectively skip items per page-type context (homepage, single, archive, …).

= How does the Update Optimizer work? =

Three strategies are available:

1. **TTL extension** — Throttle the outbound `api.wordpress.org` update HTTP calls so they only re-run after a configurable interval (12 h → 24–72 h). WordPress keeps its own cache; we only reduce how often it gets refreshed.
2. **Page-specific** — Only run update checks on the dedicated **Plugins**, **Themes** and **Updates** admin pages.
3. **Cron-only** — Move all update checks to background WP-Cron; the admin never blocks on them.

All strategies preserve update badge counts and "Check now" buttons still work as expected.

= Can I use it on multisite? =

Yes. Network activation is supported but each subsite needs its own per-site rules. The MU-loader is created once for the network.

= Does the plugin contact any external servers? =

No. See the **External Services** section above.

= What languages is the plugin translated into? =

English (source) plus Czech (cs_CZ), Slovak (sk_SK), Polish (pl_PL), German (de_DE), French (fr_FR), and Spanish (es_ES). Translations live in `/languages/` as `.po`/`.mo`. Community translations from `translate.wordpress.org` are also picked up automatically.

== Screenshots ==

1. Main dashboard showing per-screen rules for WordPress core areas.
2. Automatic mode with confidence-scored suggestions and estimated savings.
3. Hierarchical rules: group-level primary rules with screen-level overrides.
4. Admin drawer overlay for quick rule changes on any admin screen.
5. Per-plugin performance metrics with load-time and query counts.
6. Update Optimizer with three strategies and a live "stale data" indicator.
7. Request-type rules for AJAX / REST API / WP-Cron / WP-CLI.

== Changelog ==

= 1.3.9 — 2026-06-10 =
* **UPDATED** Tested with WordPress 7.0.

= 1.3.8 — 2026-05-18 =
* **NEW** Explicit user consent flow for the MU-loader install. After activation, an admin notice asks whether to install the small loader file in `wp-content/mu-plugins/`. Without consent the plugin runs in limited mode (filtering still works for later option queries; only the very first plugin-load pass is unaffected).
* **CHANGED** No more silent self-healing of the MU-loader file. The file is created only on explicit click of "Install loader file" in the admin notice, and removed automatically on deactivation.
* **FIXED** Plugin URI header now points to the WordPress.org plugin directory.
* **FIXED** Two inline `<script>` blocks in the settings page extracted to a dedicated `assets/admin-handlers.js` enqueued via `wp_enqueue_script`. The frontend bar's JSON payload now goes through `wp_add_inline_script()` instead of an inline `<script>` tag.
* **FIXED** All `$_POST` / `$_GET` / `$_SERVER` super-global reads now use `wp_unslash()` plus an explicit `sanitize_*()` helper. `$_SERVER[REQUEST_TIME_FLOAT]` is cast through `(float)` before arithmetic. `$_SERVER[REQUEST_URI]` goes through `sanitize_text_field( wp_unslash( … ) )`.
* **FIXED** All `json_decode()` results from POST payloads are now deep-sanitised by a new recursive `sanitize_rules_array()` helper before being persisted. `stripslashes()` replaced with `wp_unslash()` where applicable.
* **IMPROVED** All uses of `WP_PLUGIN_DIR` / `WP_CONTENT_DIR` annotated with explanatory comments documenting why the WordPress-provided constants are the correct API here (no `__FILE__`-relative helper exists for resolving other plugins' base paths or the must-use plugins folder at the MU-loader load stage).

= 1.3.7 — 2026-05-15 =
* **NEW** Internationalisation: ships with full Czech, Slovak, Polish, German, French, and Spanish translations.
* **NEW** Per-language `.pot`, `.po`, and `.mo` files in `/languages/`. Domain Path header added.
* **CHANGED** Plugin renamed to "ALTOS" with slug `altos` for the WordPress.org directory.
* **CHANGED** Self-hosted GitHub updater removed — WordPress.org handles updates from now on.
* **CHANGED** Update Optimizer refactored to throttle HTTP requests only; it no longer hooks the update transients (cleaner separation from WordPress's own updater).
* **FIXED** Two stray non-English strings replaced with translatable English source strings.
* **FIXED** Hardened output escaping across the admin UI (`_e()` → `esc_html_e()` etc.).
* **FIXED** Replaced `parse_url()`, `unlink()`, `date()` and `mt_rand()` with their WordPress-recommended counterparts.
* **IMPROVED** All input super-globals now go through `wp_unslash()` + `sanitize_*`.
* **IMPROVED** Stricter `phpcs:ignore` documentation on the plugin's own database queries (custom `sampling_data` table).

= 1.3.5 =
* **FIXED** MU-loader self-healing — recreates a missing MU file on `admin_init` to prevent permanent loss after a failed activation.
* **FIXED** Early translation loading warning on WP 6.7+ (`_load_textdomain_just_in_time` notice).
* **IMPROVED** MU-plugin directory resolution consistently respects the `WPMU_PLUGIN_DIR` constant.

= 1.3.2 =
* **FIXED** Self-protection in filtering: the loader can no longer block itself.
* **FIXED** Invalid frontend rule modes safely fall back to passthrough.
* **IMPROVED** Lower overhead in frontend/cache and auto-rules paths.

= 1.3.0 =
* **NEW** SHA256 package integrity validation before install.
* **IMPROVED** Frontend drawer uses a shared drawer CSS with unified visual style.
* **IMPROVED** Frontend bar JavaScript refactor (Shadow DOM mount, per-page override UX, reset flow).
* **IMPROVED** Update metadata caching strategy (lock + fallback + HTTP validators).

= 1.2.0 =
* **NEW** Automatic mode with confidence-scored suggestions.
* **NEW** Custom table for sampling data, 30-day retention.
* **NEW** Update Optimizer (TTL extension / Page-specific / Cron-only).
* **NEW** Dependency cascade detection.
* **NEW** Request-type rules (AJAX, REST API, WP-Cron, WP-CLI).
* **NEW** Per-plugin performance metrics.
* **NEW** Admin drawer overlay.
* **IMPROVED** Hierarchical rule system with global / group / screen levels.
* **IMPROVED** Smart menu preservation system.
* **IMPROVED** WooCommerce integration.
* **IMPROVED** REST API endpoints for programmatic control.

= 1.1.0 =
* **NEW** Per-screen control system.
* **NEW** Defer-loading support.
* **NEW** Admin drawer interface.
* **NEW** Performance monitoring dashboard.

= 1.0.0 =
* Initial release.

== Upgrade Notice ==

= 1.3.9 =
Tested with WordPress 7.0. No code changes.

= 1.3.8 =
Adds an explicit consent step before installing the loader file into `wp-content/mu-plugins/`. After upgrading, look for the admin notice and click "Install loader file" to keep per-screen filtering active.

= 1.3.7 =
First release published on WordPress.org. Plugin renamed to "ALTOS" (slug `altos`). Adds full translations for cs/sk/pl/de/fr/es. Recommended for all installations.

= 1.3.5 =
Bugfix release: fixes MU-plugin creation failure on Windows, self-healing MU-loader, and WP 6.7+ early translation warning.

= 1.3.2 =
Maintenance and hardening release.

= 1.2.0 =
Major update — back up your database before upgrading and test on staging first.

== Privacy ==

ALTOS stores all of its data in your own WordPress installation:

* Rules and configuration are stored in the WordPress options table.
* Performance sampling data is stored in a plugin-owned custom table (`{prefix}sapm_sampling_data`) with 30-day retention.
* No personal data about visitors or administrators is collected.

The plugin does not transmit any data to external services and does not contact any external endpoints other than throttling WordPress's existing `api.wordpress.org` update checks when the (opt-in) Update Optimizer is enabled.
