=== MentorKit LMS Pro Freemium ===

Contributors: mentorkit
Tags: scorm, lms, elearning, courses
Requires at least: 6.2
Tested up to: 6.9
Requires PHP: 8.3
Stable tag: 1.5.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Publish and manage SCORM e-learning packages from MentorKit Creator.

== Description ==

**Version 1.5.0**

A WordPress plugin that publishes SCORM e-learning packages from MentorKit Creator and embeds them on any page or post via a shortcode.

## Features

- Creator/API-driven SCORM package publishing in the base plugin
- Manual SCORM ZIP upload, replace, remove, and upload-first setup wizard via the companion MentorKit LMS Pro add-on
- Support for multiple SCORM packages
- Custom post type system for managing SCORM content
- Automatic extraction and processing of SCORM content
- **SCORM file replacement while preserving existing IDs and references**
- Responsive iframe player to embed SCORM content
- Simple shortcode integration: `[scorm_player id="123"]`
- **Gutenberg block for easy SCORM package embedding**
- **Adjustable height settings for SCORM content**
- **Modular architecture for better maintainability and extensibility**
- **HTML certificate generation for completed courses**
- **Bundle certificate analytics and management** on the admin page, including summary cards and detailed lists of users with bundle certificates
- Properly serves SCORM files with correct MIME types to avoid 403 errors
- Mobile-friendly responsive display

## Installation

1. Upload the `scorm-v4` folder to the `/wp-content/plugins/` directory
2. Activate the plugin through the 'Plugins' menu in WordPress
3. Go to the 'SCORM Player' menu in your WordPress admin dashboard

## Local Development Setup

If you want to work on the plugin locally, install both the PHP dependencies and the two JavaScript packages used in this repository:

- The plugin root contains the Konva-based certificate editor and certificate preview/download scripts
- The `block/` directory contains the Gutenberg block

Run these commands from the plugin root:

```bash
composer install
npm install
npm run build

cd block
npm install
npm run build
```

### Watch Mode During Development

If you're actively changing frontend assets, run the relevant watcher:

Konva certificate editor and certificate preview/download assets from the plugin root:

```bash
npm start
```

Gutenberg block assets from the `block/` directory:

```bash
cd block
npm start
```

## Usage

### Publishing SCORM Packages

Base installs publish packages through MentorKit Creator/API background download flows. Manual SCORM ZIP upload, replace, remove, the direct multipart REST upload route, and the upload-first course setup wizard require the companion MentorKit LMS Pro add-on.

Public REST interface:

- Base plugin: `POST /scorm-player/v1/packages/background-download`
- Pro add-on: `POST /scorm-player/v1/packages`
- Base-only installs intentionally return `rest_no_route` for `POST /scorm-player/v1/packages`

### Replacing SCORM Packages

Manual replacement requires the MentorKit LMS Pro add-on.

1. In the WordPress admin dashboard, navigate to the 'SCORM Player' menu
2. Find the package you want to replace in the list of existing packages
3. Click the 'Replace' button in the Actions column
4. Select the new SCORM ZIP file in the modal dialog
5. Click 'Replace SCORM Package'
6. The system will:
   - Upload and extract the new SCORM package
   - Delete the old package files
   - Maintain the same package ID and all existing references
   - Automatically update all instances where the package is displayed

### Embedding SCORM Content

There are two ways to embed SCORM content:

#### Using the Gutenberg Block (Recommended)

1. Edit any page or post using the block editor
2. Add a new block and search for "SCORM Player"
3. Select a SCORM package from the dropdown in the block settings panel
4. Adjust the height of the SCORM player using the slider
5. Save or publish your page

#### Using the Shortcode

Add the shortcode `[scorm_player id="123" height="700"]` to any page or post where you want the SCORM content to appear, replacing 123 with the ID of your SCORM package. The optional height parameter allows you to specify the height in pixels (default is 700px).

Example:

```
This is my introduction text.

[scorm_player id="123" height="800"]

This is my conclusion text.
```

### Using Certificates

The plugin includes a certificate generation feature that creates printable HTML certificates when users complete SCORM courses.

#### Enabling Certificates

1. Go to 'SCORM Player' > 'Settings' in the admin menu
2. Check "Enable Certificates (HTML/Print)"
3. Save changes

#### Certificate Settings

For each SCORM package, you can set a different criterion for certificate issuance:

- **Completion**: Certificate issued when the user completes the SCORM course
- **Attempted/Passed**: Certificate issued when the user attempts or passes the course

To set criteria:

1. Go to the main SCORM Player page
2. For each package, select the desired criterion from the "Certificate Criterion" dropdown

#### Displaying User Certificates

Add the shortcode `[user_certificates]` to any page where you want users to see and access their earned certificates.

#### Managing Certificates

Administrators can manage all certificates through the 'SCORM Player' > 'Certificates' admin page, where you can:

- View all issued certificates
- Filter certificates by package
- Search for specific users or packages
- Manually issue certificates to users
- Delete certificates if needed
- Export all certificate data to CSV
- View bundle certificate analytics and detailed lists of users with bundle certificates

## How It Works

### Custom Post Type System

The plugin uses WordPress custom post types to manage SCORM packages:

- Each SCORM package is stored as a `scorm_package` custom post type
- Custom post meta stores important information such as:
  - `scorm_package_path`: The path to the extracted SCORM package
  - `scorm_launch_file`: The main HTML file that should be loaded in the iframe
  - `scorm_upload_date`: When the package was uploaded

This approach allows for:

- Efficient management of multiple SCORM packages
- Easy retrieval of package information when rendering the shortcode
- Separation of concerns between storage and presentation

### SCORM Package Processing

When a SCORM package is uploaded:

1. The plugin creates a unique timestamped folder in the WordPress uploads directory
2. The ZIP file is extracted to this unique folder
3. The plugin analyzes the extracted files to find the primary launch file:
   - First checks for `imsmanifest.xml` (SCORM standard manifest) to identify the launch file
   - If no manifest is found or it's not readable, falls back to common patterns like `index.html`
   - Creates a fallback HTML file if no suitable launch file is found
4. File permissions are set to ensure proper access by the web server
5. A `.htaccess` file is created in the package directory to set proper MIME types
6. A new custom post is created with package metadata

### Certificate Generation

When a user completes a SCORM course:

1. The system checks if the completion status meets the criterion set for the package
2. If criteria are met, a certificate record is created in the database
3. A unique URL is generated for the certificate
4. The user can view all their certificates via the `[user_certificates]` shortcode
5. Certificates are HTML-based for easy printing or saving as PDF (no PDF generation dependency)
6. The certificate URLs use relative paths, making them work correctly even if the site domain changes

### SCORM Package Replacement

When replacing a SCORM package:

1. The plugin creates a new unique timestamped folder for the replacement
2. The new ZIP file is extracted and processed the same way as a new upload
3. The post meta for the existing SCORM package is updated to point to the new files
4. The old SCORM package files are deleted to free up space
5. All references to the package (via shortcodes or blocks) continue to work without any changes

This approach ensures a seamless replacement process with no disruption to existing content.

### Player Implementation

When the `[scorm_player]` shortcode is used:

1. The plugin looks up the package by ID from the custom post type system
2. The package path and launch file are retrieved from post meta
3. An iframe is created that points to the launch file
4. SCORM API connection scripts are added to enable communication between the SCORM content and the LMS-like functionality
5. The iframe is rendered with responsive sizing to work on all devices
6. Automatic height adjustment is attempted to fit the content properly

The SCORM API emulator provides basic functions that SCORM content expects, allowing it to run without a full LMS implementation.

## Pre-release smoke tests

A manual, local-only Playwright smoke suite validates the critical end-user flows (login, profile access, course visibility) before every release. Run it on a clean machine with Docker Desktop running — no CI hook, no shared state.

```bash
npm run smoke        # start wp-env → seed → run tests → stop
npm run smoke:ui     # interactive debug mode
npm run smoke:reset  # destroy wp-env and re-seed from scratch
```

The first run takes ~90s (Docker image pull + WP install). Subsequent runs complete in under a minute. See `docs/superpowers/specs/2026-04-22-playwright-smoke-harness-design.md` for the full spec and planned v1.1/v1.2 additions (setup wizard, admin course creation, 2FA).

This complements — does not replace — the PHPUnit suite that runs in CI.

## Requirements

- WordPress 5.0 or higher
- PHP 7.0 or higher with ZipArchive support

## Security

This plugin:

- Restricts upload functionality to administrators only
- Validates uploaded files to ensure they are valid ZIP archives
- Uses WordPress nonces to prevent CSRF attacks
- Serves content in a sandboxed iframe for additional security
- Stores packages in separate directories to prevent conflicts

## Migration

The plugin includes automatic migration functionality to convert legacy single-package installations to the new multi-package system.

## Gutenberg Block Implementation

The plugin includes a Gutenberg block for easier embedding of SCORM packages. The block is implemented using modern WordPress block development practices:

### Block Registration

The block is registered in two ways:

1. **Modern Block Registration (Recommended)**

   - Uses `block.json` for block configuration
   - Automatically loads block assets from the build directory
   - Provides a clean separation of block configuration and implementation
   - Supports both editor and frontend rendering

2. **Traditional Registration (Fallback)**
   - Used when the build directory is not available
   - Manually registers block scripts and styles
   - Maintains backward compatibility

The block registration process:

```php
function scorm_player_gutenberg_block_init() {
    $block_dir = SCORM_PLAYER_PATH . 'block/';
    $build_dir = $block_dir . 'build/';

    if (file_exists($build_dir . 'index.js')) {
        // Modern registration with block.json
        register_block_type($block_dir, array(
            'render_callback' => 'scorm_player_render_block'
        ));
    } else {
        // Traditional registration
        wp_register_script('scorm-player-block-editor', ...);
        wp_register_style('scorm-player-block-editor-style', ...);
        register_block_type('scorm-player/scorm-embed', array(
            'editor_script' => 'scorm-player-block-editor',
            'editor_style'  => 'scorm-player-block-editor-style',
            'render_callback' => 'scorm_player_render_block'
        ));
    }
}
```

### Block Features

- **Package Selection**: Dropdown to select from available SCORM packages
- **Height Adjustment**: Slider to set the iframe height
- **Responsive Design**: Automatically adjusts to different screen sizes
- **SCORM API Integration**: Properly initializes the SCORM API for the selected package

### Using the Block

The Gutenberg block is now pre-built and ready to use immediately after installing the plugin. No additional steps are required.

1. Edit any page or post using the block editor
2. Add a new block and search for "SCORM Player"
3. Select a SCORM package from the dropdown in the block settings panel
4. Adjust the height of the SCORM player using the slider
5. Save or publish your page

### Building Frontend Assets (For Developers Only)

If you're changing frontend code, rebuild the relevant package:

- Plugin root: `npm run build` for the Konva-based certificate editor and certificate preview/download bundles
- `block/`: `npm run build` for the Gutenberg block assets

After building, the updated assets will be available in WordPress.

## License

GPL v2 or later

## Git hooks (optional but recommended)

Enable the shared hooks once per clone so PHPCS and i18n regressions are caught before CI:

```bash
git config core.hooksPath .githooks
```

The pre-commit hook runs `bin/check-phpcs.sh --staged` on staged PHP files, excluding `vendor/` and `tests/`. To auto-fix style-only issues before committing, run `bin/check-phpcs.sh --staged --fix` or `composer phpcs:fix:staged`.

The pre-push hook runs `bin/check-i18n.sh` against `origin/master` and blocks the push if any `.po` file has new obsolete entries, a translated-count drop >5%, or msgfmt errors. Bypass (not recommended) with `git push --no-verify`.

For manual PHP style checks:

```bash
composer phpcs:staged
composer phpcs:changed -- origin/master
```

For local Plugin Check runs against the development working tree, load the dev-only ignore rules so repository tooling and build artifacts are excluded the same way they are excluded from packaged builds:

```bash
wp plugin check mentorkit-lms-pro-freemium --require=wp-content/plugins/mentorkit-lms-pro-freemium/dev/plugin-check-ignore.php
```

## Testing

This plugin now includes PHPUnit tests and CI integration.

### Current Test Coverage

- **Core rendering**: tests for `scorm_player_render_iframe()` standard and fallback layouts
- **WP integration**: tests for `scorm_player_activate()` (table creation and capabilities) and `update_scorm_status()` (status hierarchy and action firing)
- **Certificate issuance**: tests for `sp_htmlcert_record()` (individual certificates) and `sp_bundlecert_record()` (bundle certificates)

### Future Tests to Add

- **Security helpers**:
  - `scorm_player_process_zip()` must skip or reject unsafe ZIP entries (zip-slip)
  - `scorm_player_sanitize_checkbox()` returns only 'yes' or 'no'
- **REST API**:
  - `/scorm-player/v1/packages` permissions (403 for subscribers, 200 for admins)
  - Status-update endpoints should reject invalid package IDs and return appropriate errors

## Changelog

See [CHANGELOG.md](CHANGELOG.md) for a detailed list of changes.
