Created
July 20, 2023 05:15
-
-
Save seanlanglands/948ba1ba8817ed64d5e0fa4592f082f3 to your computer and use it in GitHub Desktop.
Determine whether the file is private or public based on post meta value
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
add_filter( 'vip_files_acl_file_visibility', 'check_file_visibility_by_metadata', 11, 2 ); | |
/** | |
* Given a path determine whether the file is private or public based on the | |
* value of the attachment's `_custom_restriction_meta` post meta. | |
* | |
* @param string $file_visibility one of Automattic\VIP\Files\Acl\(FILE_IS_PUBLIC | FILE_IS_PRIVATE_AND_ALLOWED | FILE_IS_PRIVATE_AND_DENIED). | |
* @param string $file_path path to file to be checked for visibility. | |
* | |
* @return string one of Automattic\VIP\Files\Acl\(FILE_IS_PUBLIC | FILE_IS_PRIVATE_AND_ALLOWED | FILE_IS_PRIVATE_AND_DENIED) | |
*/ | |
function check_file_visibility_by_metadata( string $file_visibility, string $file_path ): string { | |
// Strip the `sites/ID` part for multisite URLs, because _wp_attached_file meta doesn't store it. | |
if ( 0 === strpos( $file_path, 'sites/' ) ) { | |
$file_path = preg_replace( '#^sites/\d+/#', '', $file_path ); | |
} | |
// Reverse lookup for the attachment ID. | |
$attachment_id = get_attachment_id_from_file_path( $file_path ); | |
if ( ! $attachment_id ) { | |
return $file_visibility; | |
} | |
$attachment_restrict_file_meta = get_post_meta( $attachment_id, '_custom_restriction_meta', true ); | |
if ( (int) filter_var( $attachment_restrict_file_meta, FILTER_VALIDATE_BOOLEAN ) ) { | |
// Allow access to files for logged-in users. | |
if ( is_user_logged_in() ) { | |
return Automattic\VIP\Files\Acl\FILE_IS_PRIVATE_AND_ALLOWED; | |
} else { | |
return Automattic\VIP\Files\Acl\FILE_IS_PRIVATE_AND_DENIED; | |
} | |
} | |
return $file_visibility; | |
} | |
/** | |
* Variant of core's attachment_url_to_postid() function | |
* | |
* The core function accepts the full URL and has extra logic for reversing the host / home_uri(). | |
* | |
* In the contexts where this is used, we are only acting on the path, so we've simplified things | |
* by only accepting a file path in this function. | |
* | |
* @see https://github.com/Automattic/vip-go-mu-plugins/blob/d6892abd5092274b7591ad9a4cd0aa3d9b8e4a0e/files/acl/restrict-unpublished-files.php#L59-L107 | |
* | |
* @param $path (string) The path to resolve. | |
* | |
* @return (int) The found attachment ID, or 0 on failure. | |
*/ | |
function get_attachment_id_from_file_path( string $path ): int { | |
global $wpdb; | |
$cache_group = 'vip-files-acl'; | |
$cache_key = 'path_' . md5( $path ); | |
$attachment_id = wp_cache_get( $cache_key, $cache_group ); | |
if ( false !== $attachment_id ) { | |
return $attachment_id; | |
} | |
$attachment_id = 0; | |
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery | |
$results = $wpdb->get_results( | |
$wpdb->prepare( | |
"SELECT post_id, meta_value FROM $wpdb->postmeta WHERE meta_key = '_wp_attached_file' AND meta_value = %s", | |
$path | |
) | |
); | |
if ( $results ) { | |
// Use the first available result, but prefer a case-sensitive match, if exists. | |
$attachment_id = $results[0]->post_id; | |
if ( count( $results ) > 1 ) { | |
foreach ( $results as $result ) { | |
if ( $path === $result->meta_value ) { | |
$attachment_id = $result->post_id; | |
break; | |
} | |
} | |
} | |
} | |
wp_cache_set( $cache_key, $attachment_id, $cache_group, 5 * MINUTE_IN_SECONDS ); | |
return $attachment_id; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment