=== Livid - Video Hosting ===
Tags: video, embed, vimeo, livid, migration
Requires at least: 6.5
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 2.0.1
License: MIT
License URI: https://opensource.org/licenses/MIT

Embed Livid videos and migrate from Vimeo to Livid seamlessly.

== Description ==

Livid is a video hosting platform. This plugin serves two purposes:

1. **Enable Livid embeds** — Register Livid as an oEmbed provider so pasting Livid URLs into WordPress automatically creates video embeds, just like YouTube or Vimeo.

2. **Migrate from Vimeo** — Scan your WordPress post content for Vimeo videos and replace them with equivalent Livid videos via the Livid platform.

= Key Features =

* **Automatic embeds** — Paste any livid.com URL and it auto-embeds
* **Page builder ready** — Native Livid Video elements for Elementor, WPBakery, and Bricks, a Livid video type in Slider Revolution, plus a `[livid_video]` shortcode
* **Sensei LMS ready** — Required-video completion, automatic lesson completion, and tab-away pausing; repeated required Livid embeds are tracked separately and mixed-provider lessons wait for all required videos
* **LearnDash ready** — Livid lesson and topic embeds support LearnDash video progression, resume tracking, and completion
* **Supported-format scanning** — Finds Vimeo iframes, Gutenberg embed blocks, bare URLs, `[embed]` and `[vimeo]` shortcodes, Elementor widgets, WPBakery elements, Bricks elements, and LearnDash lesson/topic progression URLs
* **Background processing** — Scan and migration run as Action Scheduler jobs so they won't time out on large sites
* **Safe replacement** — Only replaces the specific videos you select through the Livid migration popup
* **Rollback data** — Main-content edits create a tagged WordPress revision; supported builder and LearnDash setting edits get an immutable pre-write snapshot
* **Permanent install** — Keep the plugin active for continued Livid embed support

= How It Works =

The plugin registers Livid as an oEmbed provider, which is active immediately upon installation. For migration:

1. Go to Settings > Livid and click "Find Vimeo videos" (or "Search again")
2. The plugin scans supported post content, page-builder data, and LearnDash lesson/topic progression settings for Vimeo embeds
3. A popup opens where you select which videos to migrate and map them to Livid video IDs
4. The plugin rewrites the selected embeds in the background

= Scope =

Migration scans and rewrites `post_content`, supported page-builder data for Elementor (`_elementor_data`) and Bricks (`_bricks_page_content_2`), and LearnDash's `lesson_video_url` setting for lessons/topics. Options, widget content, theme settings, and other post meta are not modified.

== Installation ==

1. Upload the plugin files to `/wp-content/plugins/livid-video-hosting/`
2. Activate the plugin through the 'Plugins' screen in WordPress
3. Go to Settings > Livid to run a migration (optional)

Livid embeds work immediately after activation. Migration requires a Livid account.

== Frequently Asked Questions ==

= Do I need a Livid account to use this plugin? =

No. The plugin enables Livid embeds for everyone. You only need a Livid account if you want to migrate existing Vimeo embeds.

= Will this break my existing Vimeo embeds? =

No. The migration only replaces the specific Vimeo embeds you select. Anything you don't select remains untouched.

= Can I undo the migration? =

Main-content edits create a WordPress revision tagged with the migration run ID. Builder and LearnDash fields are not revisioned by WordPress, so the plugin saves an immutable pre-write snapshot for those sources. Use the editor’s Revisions screen to restore pre-migration main content when available; this may also undo later post edits. There is no general one-click rollback UI for builder/setting snapshots, which require developer assistance to restore. Back up your database before running a large migration.

= What embed formats are supported? =

Gutenberg embed blocks, raw iframes, bare Vimeo URLs (auto-embeds), `[embed]` and `[vimeo]` shortcodes, Elementor widgets, WPBakery elements (both `[vc_video]` links and Vimeo iframes inside raw-HTML blocks), Bricks elements (Video elements and Vimeo iframes inside rich-text elements), and LearnDash lesson/topic video-progression URLs.

= How do I enable Sensei video completion? =

In the course editor, open Course Settings > Video. Enable Required to block completion until required videos end, Autocomplete lesson to complete automatically, and optionally Autopause. These settings affect the whole course; per-block required/optional overrides are respected. Completion requires the player's ended event. This does not enforce watching every second or prevent seeking. Looping and unavailable required videos cannot complete the lesson. Tested with Sensei LMS 4.26.4.

For a safe trial, use a temporary draft course and lesson with a Livid embed and Sensei lesson-action blocks. Use Preview as Student, verify completion is blocked before the ending, then verify Completed persists after playback. Exit preview and move the temporary content to Trash. Sensei interactive-video overlays and Sensei-specific custom video fields are not supported by this integration.

= Does the scan find every Vimeo reference? =

The migration scans supported content sources, including standard embeds in Sensei lessons. It does not search server files, arbitrary custom fields, widgets, or options. Download diagnostics report under Settings > Livid for a broader read-only database check; the report indicates skipped tables, errors, and truncation.

= Can migration progress overcount after a retry? =

Re-executing an already-completed rewrite can count it again in migration progress, while leaving the content unchanged. Verify saved content and run a fresh scan after recovering interrupted jobs.

= What happens to LearnDash learner progress after replacing a video? =

Lesson and course completion records are not changed. LearnDash derives partial playback resume data from the video URL, so an in-progress playback position resets when that URL changes from Vimeo to Livid.

== External Services ==
This plugin interacts with Livid in two ways:
1. Video migration
When you initiate a migration, the plugin sends a listing of Vimeo videos found on your site along with basic information about the pages they appear on. This is necessary so that Livid can match the Vimeo videos on your site to the ones you have uploaded to your Livid account. No data is sent unless you actively start a migration.
2. oEmbed provider
This plugin registers Livid as an oEmbed provider in WordPress. When a Livid video URL is embedded in a post or page, WordPress will make a request to Livid's oEmbed endpoint to retrieve embed information (such as the video title and player HTML). This happens whenever a post containing a Livid embed is edited or its embed cache is refreshed.
Both interactions are in line with Livid's [terms of service](https://support.livid.com/article/18-livid-terms-of-service) and [privacy policy](https://support.livid.com/article/17-livid-privacy-policy).

== Changelog ==

= 2.0.1 =
* Fix legacy Vimeo detection for protocol-relative URLs, plain links, and Elementor video widgets with missing or incorrect video types. Migrate Elementor backgrounds and HTML-widget lightbox links, converting unsupported video lightboxes to Livid watch-page links. Preserve HTTP status and server error codes in migration notices. Add diagnostics v3 with local pickup and queue health, plus warnings about Vimeography, collections, and disabled cron.

= 2.0.0 =
* Fix Sensei mixed-provider lessons whose completion buttons remained blocked by stale click handlers.
* Track repeated required Livid embeds independently so each block must finish.
* Add local integration tests and document Sensei completion setup, draft testing, recovery, and migration limitations.

= 1.9.1 =
* Bricks' native Video element with a Livid link as its File URL or dynamic-data source now matches Bricks' YouTube/Vimeo behaviour more closely: the video previews in the builder canvas instead of showing a broken player; the iframe carries the element's "Iframe title" or, failing that, the video's own title from Livid, for screen readers; and when the element has a poster image, the poster is shown and the Livid player is only loaded when clicked, as Bricks does with its provider preview images.
* Support Livid embeds in Sensei LMS lesson video progression, including required videos, automatic completion, and tab-away pausing. Preserve other required videos and completion filters; accept playback messages only from the matching Livid iframe.

= 1.9.0 =
* Bricks' native Video element now plays a Livid link given as its "File URL" source, including one pulled from dynamic data such as an ACF field inside a template or popup. Bricks treated the link as a media file and rendered a `<video>` the browser rejected; the plugin now swaps it for the Livid embed on the frontend, keeping the element's overlay and play icon, and carrying over autoplay, loop and mute.
* Migrations now use Livid's V2 popup: the whole scan is reviewed in one window and confirmed once, however many videos it holds. The plugin feeds the popup its scan in pages, receives the confirmed selection back in pages, and stores each page on the site before telling Livid it arrived, so a lost acknowledgement never causes duplicate work. Replacement jobs only start once the complete selection is stored, and a crash between storing it and scheduling the jobs is repaired automatically. Reopening the popup and confirming again replaces an unfinished transfer; a scan that has already been sent refuses a second transfer until a new search is run. If Livid does not offer the V2 popup yet, the admin page offers the classic flow as an explicit choice. Manifest post groups are now keyed by post id.
* Large scans are now handed to Livid in batches sized to Livid's request limits, instead of one manifest that failed to confirm above roughly 3,000 videos. The Livid window is reused for each batch, every batch's selection is queued into the same run so one progress bar covers the whole migration, and a batch with nothing to confirm can be skipped. Scan results are stored one batch per option rather than in one growing option, and the manifest primes post caches so building it no longer issues a query per video.
* Embeds are now verified before they are rewritten. Each embed found by a scan records where it sits among all embeds of its kind (every iframe, block or shortcode, not just the Vimeo ones) plus a fingerprint of its original source. A migration job rewrites an embed only when the saved position still holds that exact original, recognises its own replacement if it is re-run, and otherwise reports a conflict and leaves the post untouched. This fixes two bugs: when a post held the same Vimeo video twice and only one was chosen, the first occurrence was rewritten regardless; and a YouTube iframe ahead of a Vimeo one inside an Elementor or Bricks HTML widget could make the wrong iframe get rewritten. Conflicts are listed on the completion screen with a link to each post. Scans made by earlier plugin versions keep migrating exactly as before.

= 1.8.0 =
* Migrate Vimeo videos stored in Advanced Custom Fields. Tick "also check ACF custom fields" when moving from Vimeo to include links found in text, textarea, URL, oEmbed, and number fields, with an optional mode for matching plain video IDs. Every change is backed up so it can be rolled back.
* Livid video embeds now preview as the video in the block editor on WordPress.com-hosted sites, matching how they already display on the published page.

= 1.7.0 =
* Add LearnDash video progression support for Livid embeds, including bulk replacement of lesson and topic Vimeo progression URLs through the existing Livid migration flow. Preserve Vimeo-compatible resume, focus-pause, replay, and completion behavior for LearnDash and Video Resume for LearnDash, including bounded resume-seek recovery and reliable completion at the playback endpoint.

= 1.6.5 =
* The Elementor, WPBakery, and Bricks video widgets now default to matching each video's real aspect ratio automatically. The fixed ratio options (16:9, 4:3, 9:16, and the rest) are still available when you want to set one explicitly.

= 1.6.4 =
* Video blocks now display at each video's true aspect ratio automatically, so portrait, square, and widescreen videos are all sized correctly.

= 1.6.3 =
* Improved video display in centered and auto-width columns, so embeds are always sized correctly.

= 1.6.2 =
* Improved compatibility with page builders and block themes (including Stackable), so videos display reliably inside columns and flexible layouts, in the editor and on the front end.

= 1.6.1 =
* More reliable video blocks: the video URL is saved as you type, and a block added without a URL now shows a helpful notice in the editor.

= 1.6.0 =
* WPBakery background video: Livid URLs pasted into a row, section, or column's native "Video background" control now play as chromeless, cover-fit background videos. WPBakery gates its background markup on YouTube URLs server-side (and its own script removes any background container it doesn't recognise), so the plugin emits its own Livid-owned container into the rendered wrapper and a frontend handler fills it with a cover-fit embed — WPBakery's script never touches it. The control is relabelled "YouTube/Livid link" with matching help text.

= 1.5.0 =
* Slider Revolution support: add Livid as a video type in Slider Revolution 7. A "Livid" tab in the video-layer settings and a "Livid" entry in the Add-layer menu let you place Livid videos in layers and slide backgrounds, rendered as chromeless embeds. Layers are driven over the embed's Player.js API, so Slider Revolution's playback options work — autoplay, loop, start/end trim, volume, mute, next-slide-when-ends, pause-module-timer, stop-other-media, and cover-fit slide backgrounds.

= 1.4.1 =
* Fix the scan job's candidate-post query to include Bricks pages: it only looked at post_content and Elementor meta, so Bricks pages with empty post_content were never scanned. Meta keys are now derived from the registered strategies.

= 1.4.0 =
* Bricks Builder support: a first-class Livid Video element (registered from the plugin — no child theme needed), Livid URLs work in the background Video URL control (chromeless background videos) and in the link control's lightbox video option, and the migration scanner finds and converts Vimeo embeds inside Bricks pages (Video elements and iframes in rich-text elements).

= 1.3.0 =
* Livid URLs pasted into Elementor's background Video Link field now play as chromeless background videos on sections, columns, and containers. Note: previously pasted (non-functional) Livid background URLs will start playing after this update.

= 1.2.0 =
* Add WPBakery Page Builder support. A new "Livid Video" element and a general-purpose `[livid_video]` shortcode let you place Livid videos in WPBakery, and the migration now converts WPBakery Vimeo embeds — both `[vc_video]` links and Vimeo iframes inside `[vc_raw_html]`/`[vc_raw_js]` blocks. Livid oEmbed output is also hardened so embeds render correctly inside host wrappers such as WPBakery's responsive video box.

= 1.1.1 =
* Detect Elementor Video widgets whose Vimeo embed was pasted as a full `<iframe>` into the URL field (the `vimeo_url` or `youtube_url` setting), and widgets where `video_type` isn't set to "vimeo". Previously these were skipped because we required a clean Vimeo URL — now we extract the ID from the embed like Elementor itself does. Elementor's stock placeholder video is ignored so YouTube/Dailymotion widgets aren't migrated by mistake. Also tightens the diagnostics report: Elementor's derived stats/cache meta are excluded from the results, and excerpts of structured fields are longer so the full widget is captured.

= 1.1.0 =
* Add a one-click diagnostics report (Settings → Livid) that scans the whole site for Vimeo references and downloads a JSON report you can send to support. It pinpoints where each video lives — including page builders, widgets, custom fields, and other plugins' data the migration doesn't reach — so we can track down videos the migration misses. The report is read-only, takes excerpts from live content only (never revisions, trash, or drafts), and excludes passwords and customer data.

= 1.0.13 =
* chore: tidy the wp.org listing metadata — drop the `Contributors` line from readme.txt (it linked to an unrelated `livid` account) and correct the manual-install path to `/wp-content/plugins/livid-video-hosting/` to match the shipped slug.

= 1.0.12 =
* Published to the WordPress.org plugin directory. The self-hosted download now installs to `wp-content/plugins/livid-video-hosting/` to match the wp.org slug, so a site can switch to the listing and keep updating in place.

= 1.0.11 =
* Fix: WordPress admin now displays the correct plugin version.

= 1.0.10 =
* Fix: migrated Gutenberg embeds no longer inherit stale aspect-ratio classes that made them render at roughly double height.

= 1.0.6 =
* Fix: the Livid Video block toolbar and outline now appear when hovering anywhere over the player, not just its outer edge.

= 1.0.5 =
* New: Elementor support — a first-class Livid Video widget, plus Vimeo migration for Elementor pages (Vimeo Video widgets convert in place; HTML and Text Editor widgets keep their type with iframe sources swapped).

= 1.0.4 =
* New: Livid Video Gutenberg block.

= 1.0.3 =
* Fix: corrected Livid API URLs.

= 1.0.0 =
* Initial release.
* Livid oEmbed provider registration.
* Vimeo embed scanning (raw iframes, Gutenberg embed blocks, bare URLs, `[embed]` shortcodes, and `[vimeo]` shortcodes).
* Background migration via Action Scheduler.
* Livid API integration with signed manifests.

== Upgrade Notice ==

= 2.0.0 =
Improves Sensei mixed-provider completion and tracks repeated required Livid embeds independently. Existing course settings are preserved; no re-migration is required.

= 1.0.11 =
First WordPress.org release of the Livid plugin, bundling the Gutenberg block, Elementor support, and Vimeo migration tools.
