=== Discounly Unused Image Cleaner ===
Contributors: discounly
Tags: unused images, media cleaner, media library, cleanup, disk space
Requires at least: 6.2
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 4.3.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Finds unused Media Library images in minutes, even on very large sites. Check them yourself 10 at a time, then move them to the Trash.

== Description ==

= Highlights =

**Fast on large sites.** Discounly Unused Image Cleaner reads your database once, in chunks, and builds an index of every image reference, then checks each image against that index in a single pass.

Measured on real sites:

* **5,105 images (35,685 image files including resized copies), 240,000 posts and 1.9 million custom-field rows** – full scan in about 2 minutes.
* **4,132 images (27,169 files), 246,000 posts and 1.9 million custom-field rows** – full scan in under a minute.

**Every feature is free.** No Pro version, no limits on how many images you can scan or clean, no sign-up, no ads. The careful matching, the "Where is it used?" check, CSV export and the Trash view are all included.

**You stay in control.** Nothing is deleted by the scan. You check results 10 at a time, look up any image with "Where is it used?", and removal always goes to the Trash first, with each file re-checked right before it moves.

= How it works =

Over the years a WordPress site collects images that are no longer used: replaced product photos, old page designs, duplicate uploads, images from deleted posts. They take up disk space, bloat backups and make the Media Library hard to work with.

Discounly Unused Image Cleaner finds them carefully and lets you stay in control:

1. **Scan** – reads every place your site can use an image and lists the images nothing points to. Scanning only reads your site; nothing is changed.
2. **Check them yourself, 10 at a time** – see a preview, the file path, size and upload date, open the image or its Media Library page, and ask **"Where is it used?"** for any image.
3. **Full list** – every unused image, largest first, with a CSV download.
4. **Move to Trash** – removal always goes to the Trash first, and each file is re-checked right before it is moved. Restore anything from the plugin's own Trash view.

= Where it looks =

* Post, page and product content, excerpts and editor data (including Web Stories)
* Custom fields and page-builder data (Elementor and others that store JSON or serialized data)
* Featured images, WooCommerce product galleries, category and tag images
* Theme settings, Customizer, site logo and icon, widgets and plugin settings
* LearnDash quiz questions and answers, and other plugin database tables
* User profiles, comments and reviews
* Theme files, must-use plugins and generated CSS (Elementor, Astra)
* Media files that use another image (for example a video's poster)

= How it decides =

* **Full file paths, not just names.** `2023/05/banner.png` and `2021/02/banner.png` are different images.
* **Every size of an image counts.** A page that shows `photo-300x200.jpg` keeps `photo.jpg`. Scaled, rotated and edited versions are recognised.
* **Formats are different files.** `photo.jpg` and `photo.webp` are separate uploads; a page using one does not keep the other.
* **Numbers only count where an image ID belongs** – an image field, a gallery, an `<img>` class, a block or page-builder image setting. Unrelated numbers (quiz IDs, prices, view counts, element codes) are ignored.
* **Live content only.** Old revisions, trashed and auto-draft posts don't keep an image; drafts, private and scheduled posts do.
* **Catalogs and caches are ignored** – leftover media-cleaner catalogs, optimizer queues and caches list every file without using it.
* **When in doubt, it keeps the image.**

= Built for large sites =

The scan reads your database in chunks and works for about 20 seconds per request, so even a database with almost 2 million custom-field rows needs only a handful of requests. If you close the tab, the scan picks up where it left off when you come back.

= What it can't see =

No scanner can see images used only outside your WordPress database and theme files – in emails, newsletters, social posts, other websites, or code in regular plugin files. Always review the list, keep a recent backup, and use the 10-at-a-time check before moving images to the Trash.

== Installation ==

1. Upload the plugin through **Plugins → Add New → Upload Plugin**, or install it from the plugin directory.
2. Activate it.
3. Go to **Media → Unused Images** and click **Scan for unused images**.

== Frequently Asked Questions ==

= Does scanning change anything on my site? =

No. Scanning only reads your site. Nothing changes until you choose to move images to the Trash.

= Is it safe to delete what it finds? =

The plugin is careful and keeps an image whenever it isn't sure, but it cannot see images used outside your site (emails, social posts, other websites). Use "Where is it used?" and the 10-at-a-time check, keep a backup, and move images to the Trash rather than deleting them.

= Where do trashed images go? Can I get them back? =

They go to the WordPress Trash. Open **View Trash** on the plugin page to restore them or delete them permanently. Note: WordPress empties the Trash automatically after 30 days (the EMPTY_TRASH_DAYS setting).

= Why does "Where is it used?" say an image is used when I don't see it on the page? =

It may be used on a draft or private page, in a template, a product gallery, a quiz question, a setting, or a page-builder layout. The result lists the exact place, with a link where possible.

= An image I need was listed as unused. What should I do? =

Don't move it to the Trash, and please report it in the support forum with how the image is used (for example which plugin or page builder), so the scan can learn that place.

= Why are photo.jpg and photo.webp treated separately? =

They are separate uploads in your Media Library. If a page shows photo.webp, the separate photo.jpg upload is not used by that page. Copies made automatically by WebP converters (photo.jpg.webp) are recognised as belonging to the original.

= My site is large. Will the scan slow it down? =

The scan runs one request at a time, only while you have the page open, and only when you click Scan. Each request works for up to about 20 seconds. To make requests shorter, add `define( 'DISCOUNLY_UIC_STEP_SECONDS', 10 );` to wp-config.php.

= Does it work with page builders? =

It reads the data Elementor and similar builders store (JSON and serialized settings, including image IDs and URLs). It has been tested on Elementor sites. Other builders that store image URLs or IDs in post content or custom fields are covered by the same rules; please report any that aren't.

= Does it support multisite? =

It scans the current site only. Network-wide scanning is not supported yet.

= What does the plugin store? =

Its scan results and a reference index in three database tables, removed when you delete the plugin. It sends no data anywhere.

== Screenshots ==

1. Step 1 – Scan: one click, with live progress. The summary shows how many images are unused and how much space they use.
2. Step 2 – Check them yourself: 10 images at a time with preview, path, size, links to the image and its Media Library page.
3. "Where is it used?" for an image in use – every place it was found, with links.
4. "Where is it used?" for an unused image.
5. Step 3 – The full list, largest first, with CSV download and Move to Trash.
6. The plugin's Trash view – restore an image or delete it permanently.

== Changelog ==

= 4.3.0 =
* Add: a "Rate this plugin" link on the Plugins screen and on the plugin page.
* Add: after images have been moved to the Trash, a one-time note on the plugin page shows how much space was freed, with a link to leave a review. It can be dismissed for good.

= 4.2.0 =
* First release on WordPress.org.
* Update: the plugin's code, settings and database tables now use the "discounly_uic_" prefix. Data from older versions is removed automatically; run a new scan after updating.
* Update: translation-ready with the "discounly-unused-image-cleaner" text domain.
* Add: the Trash view shows how many days WordPress keeps trashed images.
* Fix: moving to the Trash is refused when the site's Trash is turned off, because WordPress would delete the images permanently.
* Fix: action buttons in the full list no longer overlap on narrow screens.

= 4.1.1 =
* New: images used in Web Stories editor data are kept.
* New: an image used as a video's poster or a media file's featured image is kept.
* Fix: page-builder and Web Stories element codes that begin with digits (such as "39cda6f") are no longer mistaken for image IDs, so more unused images are found.

= 4.1.0 =
* Much faster scans on large sites: each request works for up to ~20 seconds instead of one small batch (about 6 requests instead of ~1,500 on a site with 1.8 million custom-field rows).
* Table names and the per-request time can be set in wp-config.php.

= 4.0.0 =
* Rebuilt around one job: finding unused images.
* Full-path, size-aware and format-aware matching; image IDs only counted in image fields.
* Reads all plugin tables, comments, user profiles, theme and CSS files; ignores revisions, catalogs, queues and caches.
* New "Where is it used?" check, 10-at-a-time review, CSV export, Trash view.
* Removed duplicate, thumbnail and orphan-file features.

== Upgrade Notice ==

= 4.3.0 =
Adds a "Rate this plugin" link and a one-time, dismissible review request. No changes to scanning.

= 4.2.0 =
First WordPress.org release. Previous scan results are cleared; run a new scan after updating.
