=== Nolimit Cache ===
Contributors: kristianwind
Tags: cache, performance, woocommerce, redis, page cache
Requires at least: 6.0
Tested up to: 7.1.2
Requires PHP: 7.4
Stable tag: 0.3.2
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Full-page caching, asset optimisation, a Redis object cache and database upkeep — for WordPress and for WooCommerce, with an assistant that explains what it finds.

== Description ==

A cache plugin that says what it is doing and what each setting costs.

**Page cache.** Finished pages are written to disk and served before
WordPress, the theme or any plugin has loaded. The rules that keep that safe
are not optional: nobody signed in, nobody with a comment cookie, nobody with
anything in a basket, and never a page that did not finish rendering.

**WooCommerce awareness.** The basket, the checkout and the account pages are
excluded — found from WooCommerce's own page settings rather than guessed from
English slugs, because a Danish shop's checkout is at /kasse/. A product's page
is cleared when its stock changes or when somebody buys it, and a page built
for a visitor who already has something in their basket is never stored.

**Object cache.** An optional Redis drop-in for WordPress's own internal
lookups. On a shop this is often worth more than the page cache, because it
speeds up the pages the page cache is never allowed to touch. Clearing it is
scoped to this site, so it cannot empty another site sharing the same Redis.

**Front-end optimisation.** HTML minification, stylesheet minification,
deferred and delayed JavaScript, fewer of WordPress's default extras. All off
by default, and each option states its cost as well as its benefit. There is
deliberately no JavaScript minification and no file concatenation; the plugin
explains why on the screen where you would look for them.

**WebP and AVIF images.** Converts JPEG and PNG uploads to smaller WebP (and, if the server can, AVIF) copies that sit beside the originals, in the background and for the existing library. Pages offer the copies with a <picture> element rather than by looking at the browser, so the page cache and a CDN keep working for every visitor. The originals are never changed, and one button removes every copy. Off until you switch it on.

**Preloading.** A crawler walks the site's own sitemap in small batches so no
visitor is the one who pays for building a page.

**Database upkeep.** Revisions, auto-drafts, spam, expired transients,
abandoned WooCommerce sessions — each one counted before anything is deleted,
and a report of the autoloaded options that are read on every single request.

**Measurements, not claims.** Every request is counted, so the hit ratio on the
dashboard is measured rather than sampled, and each skipped request records
*why* it was skipped. A built-in probe times the same page with and without the
cache.

**An optional assistant.** Point it at OpenAI, Anthropic, DeepSeek, Groq,
Mistral, OpenRouter, Together, or anything else that speaks the OpenAI chat
format — including Ollama or LM Studio running on your own server, where
nothing leaves the machine at all. It reads the plugin's measurements and says
what it would change, at one of four levels from "advise only" to "change cache
settings and record how to undo it". It is off until you switch it on.

== Privacy ==

The plugin contains no analytics, no tracking and no phone-home.

It makes requests to somebody else's server in exactly two cases, and both
are listed below. It also asks THIS site for its own pages — to measure how
fast they are and to warm the cache — which leaves the server and comes
straight back to it; those are listed too, because a sentence saying "two
requests and no others" would have been false the moment you read it.

1. An update check: one unauthenticated GET for the latest release of the
   repository named in the plugin header. Nothing identifying the site is sent,
   and the user agent is overridden because WordPress's default one contains
   the site's own web address.
2. If — and only if — you configure the assistant: a request to the endpoint
   you chose. The site's name and address are not included. Email addresses, IP
   addresses and anything shaped like an API key are removed before sending.
   The exact text that would be sent can be read in wp-admin before it is sent,
   and it is assembled by the same code that sends it, so the preview and the
   request cannot differ. Listing the models a provider offers, from the
   settings screen, goes to that same provider.

To this site itself, never anywhere else:

3. Measuring the difference: two requests to your own front page, one the
   cache is not allowed to answer and one it is, which is where the
   millisecond figures on the dashboard come from.
4. Preloading, if you switch it on: your own sitemap, then your own pages, a
   few at a time, so the first real visitor is not the one who waits.

== Installation ==

1. Upload the plugin and activate it.
2. Follow the five-step guide it offers. It checks whether the site can cache
   at all before changing anything, measures the site as it is, and then
   switches the cache on.
3. Updates arrive through wp-admin like any other plugin's.

== Frequently Asked Questions ==

= Why is nothing being cached? =

Almost always one of three things, and the dashboard names which: wp-config.php
does not define WP_CACHE, wp-content is not writable, or another cache plugin
already owns wp-content/advanced-cache.php. This plugin never overwrites
another plugin's drop-in.

= Why is my hit ratio low on a shop? =

Usually because it should be. A visitor with something in their basket is
always served a fresh page, and on a busy shop that is a large share of the
traffic. The dashboard reports skipped requests separately from misses, with
the reason for each, so the number you are looking at is the one you can act
on.

= Does it work without WooCommerce? =

Yes. WooCommerce support switches itself on when WooCommerce is there.

= Can I use it with nginx? =

Yes. The page cache is served by PHP, so it does not need any server
configuration. The browser-caching rules cannot be written automatically on
nginx — the plugin gives you the snippet to hand to whoever administers the
server.

== Changelog ==

= 0.3.2 =
Nolimit Cache now tells WooCommerce that it works with High-Performance Order Storage and the Cart and Checkout blocks, so it no longer appears under "Incompatible with WooCommerce features" on the Plugins screen. Nothing else changes.

= 0.3.1 =
Fixes a fatal error on the Overview screen. Pressing "Re-run the checks" ended in "Call to undefined function get_home_path()", because the browser-cache check needs a WordPress admin file that is not loaded for that request. The plugin now loads it first. The build also checks that every admin-only WordPress function the plugin calls is loaded by the file that calls it.

The warming message now reads "1 address left in the queue" instead of "1 addresses".

The plugin's manuals are rewritten for people who run the site, and the release page now carries a landing page with screenshots.

= 0.3.0 =
New: WebP and AVIF images. Under Settings, Images, the plugin can write a smaller WebP copy (and an AVIF one, if you ask for it) of every JPEG and PNG next to the original, convert new uploads in the background, and convert the existing library from the admin screen or with `wp cache-manager images convert`. Pages offer the copies with a picture element, so the page cache and a CDN keep working. Originals are never modified, a copy that is not smaller is not kept, and the Remove button deletes every copy. The screen tells you first whether this server can write each format. Off by default.

= 0.2.9 =
Fixes a fatal error on the Assistant screen. Once the assistant was switched on,
opening it ended in "Call to undefined method NLCAC_Admin_Assistant::payload()"
and WordPress emailed the site owner about it. The rest of the site was never
affected. It had been broken since 0.2.0; the preview of what would be sent to
the AI provider is back. The build now checks that every static method the plugin
calls actually exists, which is the check that would have found this.

= 0.2.8 =
Every Nolimit Cache screen now has a row of links at the top, Overview, Settings,
Assistant and Tools, with the current one marked. Before this the sub-pages had
no sidebar entries and no way back to the front page.

On the object cache tab, a field that wp-config.php overrides with a WP_REDIS_*
constant now shows the value that is really in use and is locked, instead of the
stored value that the cache ignores.

The dashboard no longer keeps describing the site as it was before you saved.
The checks are measured again on the first page load after a settings save, so
"there is no persistent object cache" goes away once Redis is on.

= 0.2.7 =
The Redis object cache now works on servers that do not have the php-redis
extension, such as the official WordPress docker image. Where the extension is
missing it talks to Redis directly, which is slower than the extension but
still several times faster than asking the database. The object cache tab says
which of the two is in use.

The connection test now checks the Redis address the cache really connects to.
When wp-config.php defines WP_REDIS_HOST or its siblings they win over the form,
and the test used to check the form's value instead, so it could pass against a
server the cache never used. The tab now also lists which constants are
overriding which fields.

The AI key, the Redis password and the update token are no longer kept in the
main settings option, which WordPress loads on every request. They are moved to
a separate option that is not loaded automatically, once, when you update; the
copy is checked before the original is removed.

The suggestions in the Setup screen of the Nolimit Assistant plugin, added in
0.2.6, are shown from version 0.3.0 of that plugin.

= 0.2.6 =
With the Nolimit Assistant plugin installed, its Setup screen can now offer to
turn on the page cache and, once that is on, the background warming of it. On a
WooCommerce shop it also offers to put back the rule that keeps a page from
being stored for a visitor with something in their basket, should someone have
switched it off. Nothing is changed without your confirmation, and without the
Assistant plugin nothing is offered and nothing is different.

= 0.2.5 =
The small status label inside each card on the shared dashboard sat on a
background that was lightened rather than darkened, so the white text on it
was harder to read than it should be. It is darkened now. Five of the seven
plugins in the family had the same fault; they are all being changed to the
same file.

= 0.2.4 =
The plugin's colour on the shared dashboard was too light to carry the white
text written on it, so the card heading was harder to read than it should be.
It is now a slightly darker amber, and the plugin icon matches it.

The three fields that hold a secret — the AI key, the Redis password and the
update token — now ask password managers to leave them alone. A manager that
filled one of them would replace a working key rather than fill an empty box,
because the field shows bullets and saving keeps the stored value only when
the bullets come back untouched.

= 0.2.3 =
The infinity sign in the menu sat above centre, and sat wrong again in a
collapsed menu. It is now positioned by the size of the space it is in
rather than by a measurement of one particular menu state.

= 0.2.2 =
Saving a settings tab switched off every setting of that tab's that has no
control on the screen. Three did: the request counters, clearing a page when
it gets a comment, and the largest-image hint. All three default to on, so
every site that had ever pressed Save had lost them, with no message. They
are switched back on when this version is installed, and the settings form
can no longer do it.

= 0.2.1 =
The page cache no longer wraps WP-CLI commands in an output buffer. Nothing
was ever stored from one, but it held a command's output until the command
ended, which put error messages above the work that caused them.

= 0.2.0 =
The assistant is now on every screen of the plugin, not only its own page: a
panel in the corner that knows which screen you asked from, with a few
questions worth asking from where you are standing. It appears only when an
assistant is configured.

The family's menu carries an infinity sign instead of a cog.

= 0.1.4 =
The dashboard said "no traffic measured yet" on a shop that was serving every
request from the cache. It now tells you why nothing was counted, instead of
printing the sentence a quiet site would print.

Times are shown as timestamps. "Measured 2 dage ago" was half Danish and half
English on a Danish site, because WordPress answers "how long ago" in the
site's language and the word around it was ours.

= 0.1.0 =
First release.
