=== Mediachecker ===
Contributors: wpstackonline
Tags: media, media-library, unused media, orphaned attachments, cleanup, alt text, ai, duplicates, backup
Requires at least: 6.0
Tested up to: 6.6
Requires PHP: 7.4
Stable tag: 2.2.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

A security-first media library auditor that scans for unused attachments, detects duplicates, generates AI alt text, and safely cleans up your WordPress media library with automatic backups.

== Description ==

Mediachecker is a powerful, security-first media library auditor for WordPress. It scans every attachment in your media library, classifies each as used or orphaned using seven independent reference signals, and helps you reclaim storage space through safe batch deletion — with automatic backups, duplicate detection, AI-powered alt text generation, and comprehensive reporting.

Built by [Wpstack.online](https://wpstack.online) for WordPress administrators who need a reliable, transparent way to audit their media library without risking accidental data loss.

= Key Features =

**Deep Library Scan**

Walks every attachment in your media library and classifies each as used or orphaned by cross-checking seven independent reference signals:

* **Post Parent** — Attachments attached to posts/pages via `post_parent`
* **Post Meta** — Featured images, WooCommerce galleries, ACF fields, any numeric meta value referencing the attachment ID
* **Gallery Shortcodes** — `[gallery ids="..."]` shortcodes referencing the attachment ID
* **Gutenberg Blocks** — `wp:image`, `wp:gallery`, and other block JSON containing `"id"` or `"ids"` arrays
* **Filename Matching** — Full URL, base filename, and `-WxH` sized variants found in post content, theme files, widgets, and options
* **Theme Files** — PHP templates, template-parts, inc/, and style.css scanned for image references
* **Widgets** — Sidebar widget configurations serialized as JSON

Recent uploads (default 30-day window) are opt-out protected against accidental deletion.

**Batch Delete & Detach**

Select multiple orphaned media files and delete (or simply detach) them in one action:

* Confirmation modal with backup toggle, force-bypass checkbox, and dry-run preview
* Dual safety check: re-verifies references at delete time before removing anything
* Dry-run mode: preview what would happen without actually deleting
* Force flag: explicit opt-in to bypass recent-upload protection

**Automatic Backup**

Before any destructive action, Mediachecker creates a complete metadata record:

* JSON metadata export: attachment ID, title, filename, URL, MIME type, parent, date, full `wp_get_attachment_metadata()`, and backup timestamp
* ZIP packaging: bundles actual media files alongside metadata for offline recovery
* Protected storage: backup directory locked behind `.htaccess` deny-all and `index.php` silence guard
* Restore from backup: re-create attachment records from JSON with automatic file re-attachment and metadata regeneration

**Duplicate Finder**

Detects duplicate attachments by:

* Filename collision: same filename uploaded multiple times
* Content hash: identical file content (MD5) regardless of filename

Results cached for 30 minutes to avoid repeated scanning.

**AI-Powered Features**

* **Alt Text Generation** — Automatically generate accessible, descriptive alt text for images using an OpenAI-compatible vision API
* **Image Categorization** — Classify images into categories (photo, screenshot, logo, illustration, icon, document, graphic, infographic, chart, texture, other)
* **Visual Duplicate Detection** — Detect visually similar images using perceptual hashing (pHash) — runs entirely server-side, no API calls needed
* **Cleanup Confidence Scoring** — Get AI-powered recommendations with confidence scores and natural-language reasoning for each orphaned file

The vision API is OpenAI-compatible — works with OpenAI, OpenRouter, or any local LLM with an OpenAI-compatible endpoint. The perceptual hash duplicate detection runs entirely server-side with no external API calls.

**CSV Export**

Generates a portable CSV of the full scan result for reporting, audits, or compliance:

* Columns: ID, Title, File, URL, Uploaded Date, Size, MIME Type
* Filterable by status (used/unused) before export

**Scheduled Scans**

Optional WP-Cron-based automated scans with email notifications:

* Configurable interval (hourly, daily, weekly)
* Threshold-based alerts when orphan count exceeds your limit
* Notification email configurable per-site

**Security First**

Every action is gated by multiple security layers:

* Nonces: All AJAX endpoints verify `check_ajax_referer(MC_NONCE_PREFIX)`
* Capability checks: `current_user_can('manage_options')` on every endpoint
* Input sanitization: `absint()` for IDs, `sanitize_text_field()` for POST input, `filter_var()` for booleans
* Output escaping: 111+ `esc_html`/`esc_attr`/`esc_url`/`wp_kses` calls across all PHP files
* Admin-only access: Only administrators can run scans or delete media

**Activity Log**

Every delete, detach, and restore is logged for traceability:

* Timestamp, user login, action type, and detail
* Capped at 200 entries to prevent unbounded growth
* Viewable directly in the Activity Log tab

= Configuration =

Access settings via **Media → Mediachecker → Settings**:

* **Scan Theme Files** — Include PHP templates in reference detection (default: enabled)
* **Scan Post Meta** — Check postmeta table for attachment references (default: enabled)
* **Scan Widgets** — Analyze sidebar widget configurations (default: enabled)
* **Scan Options Table** — Search wp_options for upload paths (default: enabled)
* **Max Scan Time** — Timeout for scan queries in seconds (default: 300)
* **Protect Recent Uploads** — Block deletion of files uploaded within the window (default: enabled)
* **Protection Window** — Days after upload before deletion is allowed (default: 30)
* **Excluded MIME Types** — Comma-separated MIME types to skip
* **Excluded Directories** — Comma-separated upload subdirectories to skip
* **Notify on Complete** — Send email when scan finishes (default: disabled)
* **Notification Email** — Recipient for scan completion emails
* **Dry Run Default** — Pre-check the dry-run checkbox in the confirmation modal (default: enabled)
* **Show Dimensions** — Display width × height in the media list (default: enabled)
* **Show File Size** — Display file size in the media list (default: enabled)

AI settings:

* **AI API Endpoint** — OpenAI-compatible endpoint URL (default: `https://api.openai.com/v1`)
* **AI API Key** — Your API key for the vision service
* **AI Model** — Model name (default: `gpt-4o-mini`)
* **Confidence Threshold** — Minimum confidence score for cleanup recommendations (default: 70)

== Installation ==

1. Upload the `Mediachecker` folder to `/wp-content/plugins/`
2. Activate the plugin through **Plugins → Installed Plugins**
3. Navigate to **Media → Mediachecker** — the first scan runs automatically
4. Review the **Unused Media** tab to see orphaned attachments
5. Select items and click **Delete Selected** — a confirmation modal appears
6. Configure AI features in **Settings** if you want alt text generation and categorization

== Frequently Asked Questions ==

= Is it safe to delete unused media? =

Yes. Mediachecker uses a dual safety check — it re-verifies all references at delete time, not just at scan time. It also creates a JSON metadata backup before any deletion, and offers a dry-run mode to preview changes. Recent uploads are protected by default.

= Do I need an API key for the AI features? =

The alt text generation, image categorization, and confidence scoring features require an OpenAI-compatible API key. However, the visual duplicate detection (perceptual hashing) runs entirely server-side and does not need any API key.

= What happens to deleted files? =

Before deletion, Mediachecker exports metadata to JSON and optionally packages files into a ZIP archive in a protected backup directory. You can restore from backup at any time.

= Can I undo a deletion? =

Yes. The backup system stores complete metadata and optional ZIP archives. Use the restore function to re-create attachment records from the JSON backup.

= Does it work with Gutenberg/Block Editor? =

Yes. Mediachecker parses Gutenberg block JSON (`wp:image`, `wp:gallery`, etc.) to detect attachment references by ID.

= Does it work with WooCommerce? =

Yes. WooCommerce gallery images stored in post meta are detected as references.

= Does it work with ACF? =

Yes. ACF relationship and post_object fields that store attachment IDs in post meta are detected.

== Screenshots ==

1. **Dashboard** — Overview with scan statistics, used/unused counts, and reclaimable storage estimate
2. **Unused Media** — Filter, search, and select orphaned attachments for batch deletion
3. **Duplicates** — Filename collision and content hash duplicate detection
4. **AI Tools** — Alt text generation, image categorization, visual duplicates, and confidence scoring
5. **Activity Log** — Audit trail of all delete, detach, and restore actions
6. **Settings** — Configuration for scan scope, safety windows, exclusions, notifications, and AI features
7. **About** — Feature overview and step-by-step usage guide

== Changelog ==

= 2.2.0 (2025-07-19) =

* **Added:** AI alt text generation via OpenAI-compatible vision API
* **Added:** AI image categorization (photo, screenshot, logo, illustration, icon, document, graphic, infographic, chart, texture, other)
* **Added:** Visual duplicate detection using perceptual hashing (pHash) — pure PHP, no API needed
* **Added:** AI-powered cleanup confidence scoring with natural-language reasoning
* **Added:** AI Tools tab in admin dashboard
* **Added:** AI settings (API endpoint, key, model, confidence threshold)
* **Fixed:** Settings page CSS loading — assets now enqueue on all Mediachecker admin pages
* **Fixed:** AI features CSS incorrectly nested inside responsive media query — moved to top-level scope
* **Redesigned:** Admin UI — replaced gradient/glassmorphism styling with clean, WordPress-native aesthetic
* **Improved:** CSS reduced from 1764 lines to ~1440 lines by removing decorative effects

= 2.1.0 (2025-07-12) =

* **Added:** Multi-signal reference detection — 7 independent signals instead of basic post_parent check
* **Added:** Recent-upload protection — opt-out safety window (default 30 days)
* **Added:** Dual safety check on delete — re-verifies references at delete time
* **Added:** Automatic backup — JSON metadata + ZIP file packaging with protected storage
* **Added:** Duplicate finder — filename collision and content hash detection
* **Added:** CSV export — portable scan results for reporting
* **Added:** Activity log — traceable audit trail capped at 200 entries
* **Added:** Scheduled scans — WP-Cron automation with email notifications
* **Added:** About page — 8 features, 7 usage steps, Wpstack.online branding
* **Added:** Plugin row meta — Features & Guide links on Installed Plugins page
* **Added:** Activation notice — one-time welcome banner redirecting to About page
* **Added:** Transient caching — 10-minute scan cache, 30-minute duplicate cache
* **Added:** Security hardening — nonces, capability checks, sanitization, escaping throughout

= 2.0.0 =

* Initial release with basic media library scanning and unused attachment detection.

== Upgrade Notice ==

= 2.2.0 =

Major update — adds AI-powered alt text generation, image categorization, visual duplicate detection, and cleanup confidence scoring. Also includes a complete UI redesign with a clean WordPress-native aesthetic. Recommended for all users.

== License ==

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
