Skip to content

Developer Overview

MediaShield overviewFree + ProGet MediaShield →

This section is for developers extending or integrating MediaShield Pro. For site-owner documentation, see Getting Started.

Item Value
PHP namespace MediaShieldPro\
REST namespace mediashield-pro/v1
Text domain mediashield-pro
Free plugin required MediaShield (any active version)
Version documented 1.3.0

Pro’s only dependency check is defined( 'MEDIASHIELD_VERSION' ) - it does not compare version numbers. Free and Pro are released in lockstep, so run matching versions (1.3.0 with 1.3.0).

MediaShield Pro extends the free plugin through WordPress hooks, filters, and free’s public static helpers. It never:

  • Registers routes under mediashield/v1 (free’s REST namespace).
  • Adds a top-level admin menu of its own – it injects pages into free’s React admin SPA via the mediashield_admin_routes JS filter.

It does read some free-owned options directly (ms_enabled, ms_show_badge) and calls free classes directly (MediaShield\Access\AccessControl::can_watch(), MediaShield\Access\SessionManager::validate_token()). Free treats those as public API; do not assume the boundary is hook-only.

Pro bootstraps on plugins_loaded at priority 20, after free’s default-priority bootstrap, guarded by the MEDIASHIELD_VERSION constant:

plugins_loaded (priority 10)
free plugin initializes
plugins_loaded (priority 20)
Pro checks defined( 'MEDIASHIELD_VERSION' )
-> Migrator::run(), Plugin::instance()
-> registers REST, hooks, subsystems
-> fires mediashield_pro_loaded

Pro does not hook mediashield_loaded. That action exists in free but has no subscribers; load order is carried by the priority gap plus the constant guard. Hook mediashield_pro_loaded if you need to run after Pro is ready.

Subsystem Purpose
Access Per-video role restriction (Access\RoleAccess)
Analytics Heatmap aggregation, realtime viewers, suspicious-activity alerts, optional VPN lookup, playback-event recording
Platform Bunny, YouTube, Vimeo, and Wistia connections, browsing, and import
Upload Platform upload drivers and the ms_upload_queue job log
DRM ClearKey key storage and license issuance. No packaging - that code was removed in 1.3.0. See below
LMS Auto-completion and enrollment gating for LearnDash, Tutor LMS, LifterLMS
Watermark Advanced watermark configuration (7 fields)
Milestones Webhook, email, and user-meta actions on milestone events
Ads Per-video in-video ad selection on top of free’s ad-manager bridge
Export Streaming CSV and async PDF reports
Licensing Pro license activation and status (updates only, no feature gating)
Reports Weekly engagement digest email
Privacy GDPR exporter and eraser for Pro-owned tables

DRM caveat: the packaging code was deleted in 1.3.0 because nothing called it. No content key is generated by the plugin, and POST /drm/license returns drm_key_not_found. No Shaka Player build is bundled or enqueued by either plugin, so assets/js/drm-player.js bails with a console warning unless the site loads Shaka itself. Treat the DRM subsystem as unproven plumbing, not a shipping feature.

MediaShield\Access\AccessControl::can_watch() runs free’s own checks first - admin bypass, login gate, per-video role gate (_ms_access_role), domain restriction - and only then applies the mediashield_can_watch filter. Subscribers on that filter:

Priority Subscriber Decision
20 Pro Access\RoleAccess Per-video role restriction (_ms_access_role)
25 Pro LMS adapters Enrollment gate, per video via _ms_lms_require_enrollment

Every subscriber returns early when $result['allowed'] is already false, so a denial from an earlier callback stands. Pick a priority outside 20-25 for custom callbacks.