# Changelog

All notable changes to the SQMViews plugin will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

### Planned
- Dashboard enhancements
- Additional export formats
- Bot filtering

## [Unreleased]

## [1.2.4] - 2026-03-16

### Added
  - Dashboard: Table view — new chart type showing data in a tabular format with sorting
  - Dashboard: URL state syncing — chart filters and chart type are persisted in the URL for shareable links
  - Dashboard: CSV and PNG export — export chart data as CSV or save the chart as a PNG image
  - Dashboard: Dynamic Y-axis rescaling — Y-axis adjusts automatically when toggling series in the legend, making smaller data visible after hiding large series
  - Dashboard: Clickable legend links — article IDs in the "By Content" legend are now links to the article page; clicking the title still toggles the series
  - Charts API: Article URLs — the by_content series response now includes a url field with the post permalink
  - Drop-in: Versioned archive — the build script now produces a separate versioned drop-in zip for the fast endpoint
  - Drop-in added to the plugin as sqm-views-pages.template, added functionality to install drop-in from the admin interface

### Changed
  - Charts API: simplified post title resolution to individual cached queries instead of batch lookups
  - Drop-in: applied the same security measures as the main plugin (input validation, sanitization)
  - Ensured ABSPATH and SQMVIEWS_WP_UPLOADS are defined before utils.php is loaded via autoloader

---


## [1.1.9] - 2026-02-01
First official release

---

## [1.1.8] - 2025-12-09

### Fixed
  - Drop-in script removed from the main distribution

---


## [1.1.5] - 2025-12-02

### Bug Fixes

  - Activation fix - Suppressed database errors during index/constraint creation to prevent failures on re-activation
  - Drop-in handling - Skip drop-in creation if it already exists, preventing duplicate file issues

### Security & Validation

  - Safe redirects - Using wp_safe_redirect for improved security
  - Input validation - Added page filter validation and data sanitization
  - Removed unused filters - Cleaned up unused WordPress filters

### Code Quality

  - WordPress coding standards - Full PHPCS compliance
  - PHPStan fixes - Resolved static analysis findings
  - Namespaced global variables - Better isolation of plugin globals
  - Unit tests - Added tests for records processing

### Configuration

  - Logger defaults - Set verbose to false and log level to CRITICAL for production
  - Environment override - Allow SQMVIEWS_WP_UPLOADS override via environment variable for CI/Docker
  - Dynamic paths - Replaced static paths with dynamic plugin-based resolution

### Compatibility

  - Updated the tested WordPress version to 6.9

### Build

  - Updated Composer dependencies

---


## [1.1.4] - 2025-11-07

### Changed
Minor update. Readme file improved. Screenshots removed from a zip file.

---


## [1.1.2] - 2025-10-26

Screenshots added
Last touches before plugin submission

---


## [1.1.0] - 2025-10-26

 ### Added
  - Fast endpoint detection via SQMVIEWS_FAST_ENDPOINT constant to distinguish between PHP drop-in and REST API methods
  - POT file auto-regeneration in version bump script

  ### Changed
  - Test endpoint now returns lightweight response on fast endpoint (skips diagnostics)
  - WordPress filter hooks (session_timeout, ping_interval) now bypassed on fast endpoint for performance
  - The default log level changed from INFO to ERROR in production (DEBUG when WP_DEBUG is true)
  - Admin timestamp display now uses the site timezone instead of UTC

  ### Technical Details
  - Test endpoint response includes the 'endpoint' field ('fast' or 'api')
  - Fast endpoint identified by constant defined in sqm-views-pages.php

---


## [1.0.7] - 2025-10-26
  - Maintenance release – version bump only
  - No functional changes to the plugin

---


## [1.0.5] - 2025-10-18
  Added

  - Execution timeout handling in statistics processor to prevent script timeouts when processing large numbers of files
    - Automatic detection of PHP max_execution_time with 20% safety buffer
    - Graceful loop breaking when approaching timeout threshold
    - Detailed logging of timeout events with diagnostic information
    - Support for unlimited execution time (max_execution_time = 0)

  Changed

  - Incomplete record handling during timeout scenarios - all incomplete records now saved to incomplete file instead of stale file when timeout occurs
  - Processing status messages now distinguish between complete processing and partial processing due to timeout
  - Database query construction in charts API - replaced dynamic SQL construction with explicit prepared statements using proper placeholders for better security and maintainability
  - Input sanitization in SQMViewsRapidProcessor - changed from wp_unslash() to stripslashes() for $_SERVER variables

  Fixed

  - WordPress Coding Standards compliance in SQMViewsSettings.php:
    - Added nonce verification for admin message display
    - Added proper wp_unslash() and sanitization for all $_GET parameters
    - Fixed 12 security warnings related to nonce verification and input validation
  - SQL injection prevention in charts API - eliminated implode() concatenation in WHERE clauses, now using separate query branches with full placeholder support
  - Error handling in SQMViewsRapidProcessor - fixed variable reference bug in event validation error response (line 249: now correctly uses $event_validation_result instead of undefined $validation_result)

  Technical Details

  - Timeout detection occurs after processing complete and invalid records for each file
  - Already-processed files are still archived even when timeout occurs
  - Stale record logic is bypassed during timeout to ensure data continuity for next run
  - Chart API queries now use 4 explicit query variations based on filter combinations (both eid+tid, only eid, only tid, no filters)

---


## [1.0.4] - 2025-10-10

### Added
Internationalization scelon.
Debug versions for tracking and dashboard javascripts
Version management tools.
Updated readme and plugin metadata.
Uninstall plugin tools.
Plugin can detect updates and run update code.

---


## [1.0.3] - 2025-10-09

### Added
- Initial stable release
- Client-side JavaScript tracking with init, ping, exit, and timeout events
- Ultra-fast tracking endpoint bypassing WordPress load
- Batch statistics processing via WordPress Cron
- REST API for data retrieval and charts
- Interactive dashboard with D3.js visualizations
- WordPress admin interface for configuration
- WP-CLI commands for manual processing
- Comprehensive hook system (30+ hooks for extensibility)
- Support for tracking posts, taxonomies, archives, and special pages
- Database schema with optimized indexes
- File-based raw data storage with automatic archiving
- Session management with configurable timeouts
- Encryption for tracking payloads
- Support for both inline and external JavaScript loading
- Configurable cron intervals (15min, hourly, 6 hours, daily, weekly)

### Features
- **Tracking Metrics:**
  - Page view count
  - Time on page (total and active)
  - High-frequency interactions (scroll, mouse moves)
  - Low-frequency interactions (clicks, touches, keypresses)

- **Data Processing:**
  - Batch processing of JSONL files
  - Daily aggregation for optimized queries
  - Incomplete session handling
  - Automatic file archiving

- **API Endpoints:**
  - `POST /wp-json/sqm-views/v1/track` - Tracking endpoint
  - `GET /wp-json/sqm-views/v1/charts` - Charts data endpoint

- **Admin Pages:**
  - Tracking Settings - Configure trackable post types and taxonomies
  - Processing Settings - Configure cron intervals and handlers
  - Statistics Dashboard - Interactive charts and analytics

- **Extensibility:**
  - 15 tracker and frontend hooks
  - 8 data processing hooks
  - 3 REST API hooks
  - 4 activation and configuration hooks

### Technical
- PHP 8.1+ compatibility
- WordPress 6.0+ compatibility
- PSR-4 autoloading
- WordPress Coding Standards compliant
- Comprehensive PHPDoc documentation

---

## Versioning Strategy

This plugin follows [Semantic Versioning](https://semver.org/) (MAJOR.MINOR.PATCH):

- **MAJOR**: Incompatible API changes or major feature overhauls
- **MINOR**: New functionality in a backward-compatible manner
- **PATCH**: Backward-compatible bug fixes

### Version Locations

The version number is maintained in multiple locations:

1. **`src/includes/utils.php`** - PHP constant `SQMVIEWS_VERSION` (source of truth)
2. **`sqm-views.php`** - WordPress plugin header `Version:` field
3. **`composer.json`** - Composer package version
4. **`VERSION`** - Plain text version file (for automation)
5. **`CHANGELOG.md`** - Version history and changes

### Updating Version

**Automated (Recommended):**

Use the `bump-version.sh` script which automates the entire process:

```bash
# Bump patch version (1.0.0 -> 1.0.1)
./bump-version.sh patch

# Bump minor version (1.0.0 -> 1.1.0)
./bump-version.sh minor

# Bump major version (1.0.0 -> 2.0.0)
./bump-version.sh major

# Set specific version
./bump-version.sh 1.2.3

# Commit and tag locally without pushing
./bump-version.sh patch --no-push
```

The script will:
1. Check for uncommitted changes (fails if any)
2. Update version in all files
3. Open editor to document changes in CHANGELOG.md
4. Create git commit with version message
5. Create annotated git tag (v1.x.x)
6. Push commit and tag to remote (optional)

**Manual:**

When releasing a new version without the script:

1. Update `SQMVIEWS_VERSION` constant in `src/includes/utils.php`
2. Update plugin header version in `sqm-views.php`
3. Update `version` field in `composer.json`
4. Update `VERSION` file
5. Add entry to `CHANGELOG.md` with date and changes
6. Create git tag: `git tag -a v1.0.0 -m "Release version 1.0.0"`
7. Push tag: `git push origin v1.0.0`

### Version Check in Code

To check the plugin version programmatically:

```php
// Get version constant
$version = SQMVIEWS_VERSION;

// Check WordPress plugin data
if ( function_exists( 'get_plugin_data' ) ) {
    $plugin_data = get_plugin_data( __FILE__ );
    $version = $plugin_data['Version'];
}
```

---

**Note:** JavaScript tracker files (`sqm-views-pages-*.js`) use a separate versioning scheme in their filename (e.g., `0.0.0`) which should be updated independently when the tracker API changes.
