# Meta Ledger - Track, compare, and restore post meta Changes

[![WordPress Plugin Version](https://img.shields.io/wordpress/plugin/v/meta-ledger)](https://wordpress.org/plugins/meta-ledger)
[![WordPress Plugin Rating](https://img.shields.io/wordpress/plugin/rating/meta-ledger)](https://wordpress.org/plugins/meta-ledger)
[![WordPress Plugin Downloads](https://img.shields.io/wordpress/plugin/dt/meta-ledger)](https://wordpress.org/plugins/meta-ledger)

**Automatically track all post meta changes with versioned history, field-level diffs, and restore functionality.**

Meta Ledger is a powerful WordPress plugin that automatically tracks every change to post meta fields, providing a complete audit trail with version history, source tracking, and one-click restore functionality. Perfect for developers, content managers, and anyone who needs to track and manage post meta changes.

## Features

### 🔍 Automatic Tracking
- Automatically hooks into WordPress meta functions to track all changes
- Works with posts, pages, custom post types, and WooCommerce products
- Zero configuration required - starts tracking immediately after activation

### 📜 Complete Version History
- View complete history of all meta changes with timestamps
- See who made each change (user tracking)
- Color-coded action types (Added, Updated, Deleted)
- Track changes made from code or the Meta Ledger UI

### 🔄 Restore Functionality
- One-click restore to any previous version
- Restore individual meta fields without affecting others
- Safe restore process with automatic history tracking

### 📍 Source Tracking
- See exactly which file and line triggered each meta change
- View function names and stack traces
- Identify changes made from Meta Ledger UI vs. code changes
- Click to view source location details in a popover

### ✏️ Inline Editing
- Edit meta values directly from the Meta Values tab
- Add new meta fields with a simple form
- Delete meta fields with confirmation
- Changes are automatically tracked with source attribution

### 🎨 Modern UI
- Clean, tabbed interface (Meta Values & History)
- Search and filter meta keys
- Collapsible history groups by meta key
- Refresh button to reload history
- Responsive design that works on all screen sizes

### ⚡ Performance Optimized
- Efficient database storage with JSON compression
- Configurable retention policies
- Automatic cleanup of old versions
- Skips high-frequency WordPress internal meta keys by default

### 🔌 Developer Friendly
- REST API endpoints for programmatic access
- WP-CLI commands for command-line operations
- WordPress filters for customization
- Clean, well-documented code following WordPress standards

## Requirements

- **WordPress**: 6.0 or higher
- **PHP**: 8.0 or higher

## Installation

1. Upload the `meta-ledger` folder to `/wp-content/plugins/`
2. Activate the plugin through the 'Plugins' menu in WordPress
3. The database table will be created automatically on activation

## Usage

### Admin Interface

After activation, a **Meta Ledger** meta box appears below the post editor on all tracked post types.

#### Meta Values Tab
- View all current meta values for the post
- Edit values inline with the save button
- Add new meta fields using the "Add New Meta" button
- Delete meta fields with the trash icon
- Search meta keys using the search box

#### History Tab
- View complete change history grouped by meta key
- See old and new values side-by-side
- Click source buttons to view file location details
- Restore any version with one click
- Refresh button to reload latest history
- Expandable groups to view all changes for a meta key

### Settings Page

Navigate to **Settings → Meta Ledger** to configure:

- **Post Types**: Select which post types to track (default: posts, pages, products)
- **History Entries per Meta Key**: Maximum number of versions to keep (default: 50)
- **Ignored Meta Keys**: List of meta keys to exclude from tracking (one per line, supports wildcards)

### REST API

Access meta history programmatically via REST API:

```bash
# Get all history for a post
GET /wp-json/meta-ledger/v1/history/{post_id}

# Get history for a specific meta key
GET /wp-json/meta-ledger/v1/history/{post_id}/{meta_key}

# Restore a version
POST /wp-json/meta-ledger/v1/restore
Body: {
  "post_id": 123,
  "meta_key": "_price",
  "index": 0
}
```

**Example:**
```bash
curl -X GET "https://yoursite.com/wp-json/meta-ledger/v1/history/123" \
  -H "X-WP-Nonce: YOUR_NONCE"
```

### WP-CLI Commands

**Show meta history:**
```bash
wp meta-ledger show <post_id> [--meta_key=<key>] [--limit=<number>] [--format=<format>]
```

**Restore a version:**
```bash
wp meta-ledger restore <post_id> <meta_key> <index> [--yes]
```

**Cleanup old versions:**
```bash
wp meta-ledger cleanup [--retention=<number>] [--yes]
```

**Examples:**
```bash
# Show all meta history for post 123
wp meta-ledger show 123

# Show only _price meta changes
wp meta-ledger show 123 --meta_key=_price --limit=10

# Restore the first version of _price meta
wp meta-ledger restore 123 _price 0 --yes
```

## Filters

### `meta_ledger_ignored_meta_keys`

Filter the list of ignored meta keys.

```php
add_filter( 'meta_ledger_ignored_meta_keys', function( $keys ) {
    $keys[] = '_my_custom_key';
    return $keys;
} );
```

### `meta_ledger_tracked_post_types`

Filter the list of tracked post types.

```php
add_filter( 'meta_ledger_tracked_post_types', function( $post_types ) {
    $post_types[] = 'my_custom_post_type';
    return $post_types;
} );
```

### `meta_ledger_skip_tracking`

Temporarily skip tracking for specific operations.

```php
Meta_Ledger_Core::set_skip_tracking( true );
// ... do meta operations that won't be tracked ...
Meta_Ledger_Core::set_skip_tracking( false );
```

## Database Schema

The plugin creates a custom table `{prefix}_meta_ledger_versions` with the following structure:

| Column | Type | Description |
|--------|------|-------------|
| `id` | BIGINT | Primary key |
| `post_id` | BIGINT | Linked post/CPT/product ID |
| `meta_key` | VARCHAR(255) | Meta field key |
| `history` | LONGTEXT | JSON array of version history |
| `updated_at` | DATETIME | Last update timestamp |

Each history entry contains:
- Timestamp
- Action (add, update, delete)
- User ID
- Old value
- New value
- Source file, line, and function
- Stack trace

## Performance

- **Efficient Storage**: Uses JSON compression to store multiple versions per row
- **Indexed Queries**: Database indexes on `post_id` and `meta_key` for fast retrieval
- **Smart Filtering**: Automatically skips WordPress internal meta keys (`_edit_lock`, `_edit_last`, etc.)
- **Configurable Retention**: Set how many versions to keep per meta key
- **Batch Processing**: Changes are batched and inserted at shutdown for optimal performance

## Frequently Asked Questions

**Q: Which post types are tracked?**  
A: By default, Meta Ledger tracks posts, pages, and WooCommerce products. You can add more post types in Settings or using the `meta_ledger_tracked_post_types` filter.

**Q: How do I ignore certain meta keys?**  
A: Navigate to Settings → Meta Ledger and add meta keys to ignore (one per line). You can also use the `meta_ledger_ignored_meta_keys` filter.

**Q: Will this slow down my site?**  
A: Meta Ledger is designed for performance. It uses indexed database queries, batches changes, and skips high-frequency meta keys by default. The impact is minimal.

**Q: Can I restore multiple meta fields at once?**  
A: Currently, you restore one meta field at a time. This ensures precision and prevents accidental bulk changes.

**Q: Does it track changes made from other plugins?**  
A: Yes! Meta Ledger tracks all changes made through WordPress meta functions, regardless of the source (plugins, themes, or custom code).

## Support

For issues, feature requests, or contributions, please visit the [plugin support forum](https://smilingsyntax.com/plugin/meta-ledger) or contact the plugin author.

## License

This plugin is licensed under the **GPLv2 or later**.

## Changelog

### 1.0.1
- Settings link on plugins page (links to Meta Ledger settings)
- Fix restore failing when value unchanged or already deleted (`meta_ledger_restore_failed`)
- View full value: click long old/new values in history to open a popover
- Side-by-side diff view: old vs new values in a diff-checker style popover
- Improved value popover with colored columns (old = red tint, new = green tint)

### 1.0.0
- Initial release
- Automatic meta tracking for posts, pages, and custom post types
- Version history UI with tabbed interface (Meta Values & History)
- Inline meta editing with add/delete functionality
- Restore functionality with one-click restore
- Source file and line tracking with popover details
- Source tracking for changes made from Meta Ledger UI
- Refresh button on History tab
- REST API endpoints for programmatic access
- WP-CLI commands (show, restore, cleanup)
- Settings page with post type selection, retention, and ignore options
- Performance optimizations with batching and caching
- WooCommerce product support
- Responsive design
