Skip to content

Fix media library attachment label for course/membership-protected files#3181

Open
faisalahammad wants to merge 1 commit into
gocodebox:devfrom
faisalahammad:fix/3166-media-protection-attachment-label
Open

Fix media library attachment label for course/membership-protected files#3181
faisalahammad wants to merge 1 commit into
gocodebox:devfrom
faisalahammad:fix/3166-media-protection-attachment-label

Conversation

@faisalahammad

@faisalahammad faisalahammad commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary

When a file was protected by a course or membership via the File block lock icon, the WP Media Library attachment detail screen showed the Assignments add-on label "protected as an assignment submission" instead of the core label "Access is restricted to the selected course/membership."

The add-on hook llms_media_protection_attachment_field was running for every protected file, so any add-on could overwrite core labels. This scopes the filter to add-on-protected files only and exposes the authorization hook name so callers can identify who owns the protection.

Fixes #3166

Changes

includes/class-llms-media-protector.php

Before:

public function is_media_protected( $media_id ) {
    return (bool) get_post_meta( $media_id, self::AUTHORIZATION_FILTER_KEY, true );
}

After:

public function is_media_protected( $media_id ) {
    return (bool) get_post_meta( $media_id, self::AUTHORIZATION_FILTER_KEY, true );
}

/**
 * Get the authorization filter hook name for a protected media file.
 *
 * Returns the name of the filter hook that controls access to the file,
 * or an empty string if the file is not protected.
 *
 * @since 9.0.0
 *
 * @param int $media_id The post ID of the media file.
 * @return string Filter hook name, or empty string if not protected.
 */
public function get_authorization_filter_name( $media_id ) {
    return (string) get_post_meta( $media_id, self::AUTHORIZATION_FILTER_KEY, true );
}

Why: Add-ons and admin UI need a way to know which protection hook owns a file. is_media_protected() only returns a boolean, so labels could not be matched to the correct protection type.

includes/admin/class-llms-admin-media-protection-attachment-settings.php

Before:

$form_fields['llms_media_protection_post'] = array(
    'label' => __( 'LifterLMS Media Protection:', 'lifterlms' ),
    'input' => 'html',
    'html'  => "$protection_warning_html<select ...>$selected_product_html</select>",
    'helps' => '',
);

/**
 * Filter the LifterLMS media protection attachment field.
 *
 * @param array $field Attachment field.
 * @param WP_Post $post Attachment post.
 * @param LLMS_Media_Protector $protector Media protector instance.
 */
$form_fields['llms_media_protection_post'] = apply_filters( 'llms_media_protection_attachment_field', $form_fields['llms_media_protection_post'], $post, $protector );

After:

$auth_filter        = $protector->get_authorization_filter_name( $post->ID );
$is_addon_protected = $auth_filter && 'llms_attachment_is_access_allowed' !== $auth_filter;
$is_core_protected  = $protector->is_media_protected( $post->ID ) && ! $is_addon_protected;

$form_fields['llms_media_protection_post'] = array(
    'label' => __( 'LifterLMS Media Protection:', 'lifterlms' ),
    'input' => 'html',
    'html'  => "$protection_warning_html<select ...>$selected_product_html</select>",
    'helps' => $is_core_protected ? sprintf( __( 'Access is restricted to the selected course/membership. %1$sLearn More%2$s', 'lifterlms' ), '<a target="_blank" href="https://lifterlms.com/docs/how-protected-media-files-work/?utm_source=LifterLMS%20Plugin&utm_medium=Media&utm_campaign=Backend%20Help%20Page">', '</a>' ) : '',
);

if ( $is_core_protected ) {
    return $form_fields;
}

/**
 * Filter the LifterLMS media protection attachment field.
 *
 * Only runs for unprotected files or files protected by add-ons (i.e., a filter hook
 * other than the default 'llms_attachment_is_access_allowed'). Core-protected files
 * use the standard label and help text above so add-ons cannot overwrite them.
 *
 * @since 10.0.0
 *
 * @param array                $field     Attachment field definition.
 * @param WP_Post              $post      Attachment post object.
 * @param LLMS_Media_Protector $protector Media protector instance.
 */
$form_fields['llms_media_protection_post'] = apply_filters( 'llms_media_protection_attachment_field', $form_fields['llms_media_protection_attachment_field'], $post, $protector );

Why: Files protected by core course/membership protection now show the correct label directly. The add-on filter still runs for its own files (different authorization hook name) and for unprotected files, so backwards compatibility is preserved.

Testing

Test 1: Course-protected file shows correct label

  1. Create a course.
  2. Add a File block to a lesson, upload a file, and click the lock icon.
  3. Select the course and click "Protect Image".
  4. Go to WP Admin → Media → Library and open the file details.
  5. Confirm the help text says: "Access is restricted to the selected course/membership."

Result: Works as expected.

Adds get_authorization_filter_name() to LLMS_Media_Protector so callers can identify which protection hook owns a file. Scopes llms_media_protection_attachment_field so it only runs for unprotected files or add-on-protected files, preventing add-ons like Assignments from overwriting the core course/membership label.

Fixes gocodebox#3166
@faisalahammad faisalahammad requested a review from brianhogg as a code owner June 15, 2026 17:26
@brianhogg brianhogg moved this to Awaiting Review in Development Jun 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Awaiting Review

Development

Successfully merging this pull request may close these issues.

2 participants