Last active
January 12, 2021 23:08
-
-
Save mjangda/8657cfde2b2a4cafd95f509dd1d3dde9 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 | |
<?php | |
namespace Automattic\VIP\Files\Acl; | |
use WP_Error; | |
class VIP_Files_Acl_Unpublished_Files_Test extends \WP_UnitTestCase { | |
const TEST_IMAGE_PATH = VIP_GO_MUPLUGINS_TESTS__DIR__ . '/fixtures/image.jpg'; | |
public static function setUpBeforeClass() { | |
parent::setUpBeforeClass(); | |
require_once( __DIR__ . '/../../files/acl/vip-private-files-unpublished-files.php' ); | |
} | |
public function test__get_file_path_from_attachment_id__attachment_not_found() { | |
$attachment_path = '/2020/12/not-an-attachment.pdf'; | |
$expected_attachment_id = 0; | |
// Run the test. | |
$actual_attachment_id = get_file_path_from_attachment_id( $attachment_path ); | |
$this->assertEquals( $expected_attachment_id, $actual_attachment_id ); | |
} | |
public function test__get_file_path_from_attachment_id__attachment_only_one_result() { | |
// Set up a test attachment. | |
$expected_attachment_id = $this->factory->attachment->create_upload_object( self::TEST_IMAGE_PATH ); | |
list( $attachment_src ) = wp_get_attachment_image_src( $expected_attachment_id, 'full' ); | |
$attachment_path = parse_url( $attachment_src, PHP_URL_PATH ); | |
$attachment_path = $this->strip_wpcontent_uploads( $attachment_path ); | |
// Run the test. | |
$actual_attachment_id = get_file_path_from_attachment_id( $attachment_path ); | |
$this->assertEquals( $expected_attachment_id, $actual_attachment_id ); | |
} | |
public function test__get_file_path_from_attachment_id__attachment_multiple_results_first_in_list() { | |
// Set up the first attachment. | |
$attachment_id = $this->factory->attachment->create_upload_object( self::TEST_IMAGE_PATH ); | |
// Create a second attachment with the same file path. | |
$duplicate_attachment_id = $this->factory->attachment->create_upload_object( self::TEST_IMAGE_PATH ); | |
$duplicate_attachment_file = get_post_meta( $duplicate_attachment_id, '_wp_attached_file', true ); | |
update_post_meta( $duplicate_attachment_id, '_wp_attached_file', $duplicate_attachment_file ); | |
// Look up the first one in the list. | |
$expected_attachment_id = $attachment_id; | |
list( $attachment_src ) = wp_get_attachment_image_src( $expected_attachment_id, 'full' ); | |
$attachment_path = parse_url( $attachment_src, PHP_URL_PATH ); | |
$attachment_path = $this->strip_wpcontent_uploads( $attachment_path ); | |
// Run the test. | |
$actual_attachment_id = get_file_path_from_attachment_id( $attachment_path ); | |
$this->assertEquals( $expected_attachment_id, $actual_attachment_id ); | |
} | |
public function test__get_file_path_from_attachment_id__attachment_multiple_results_exact_match_first() { | |
// Set up the first attachment. | |
$attachment_id = $this->factory->attachment->create_upload_object( self::TEST_IMAGE_PATH ); | |
// Create a second attachment with the same file path. | |
$duplicate_attachment_id = $this->factory->attachment->create_upload_object( self::TEST_IMAGE_PATH ); | |
$duplicate_attachment_file = get_post_meta( $duplicate_attachment_id, '_wp_attached_file', true ); | |
update_post_meta( $duplicate_attachment_id, '_wp_attached_file', strtoupper( $duplicate_attachment_file ) ); | |
// Look up the second one in the list. | |
$expected_attachment_id = $duplicate_attachment_id; | |
list( $attachment_src ) = wp_get_attachment_image_src( $expected_attachment_id, 'full' ); | |
$attachment_path = parse_url( $attachment_src, PHP_URL_PATH ); | |
$attachment_path = $this->strip_wpcontent_uploads( $attachment_path ); | |
// Run the test. | |
$actual_attachment_id = get_file_path_from_attachment_id( $attachment_path ); | |
$this->assertEquals( $expected_attachment_id, $actual_attachment_id ); | |
} | |
private function strip_wpcontent_uploads( $path ) { | |
return substr( $path, strlen( '/wp-content/uploads/' ) ); | |
} | |
} |
This file contains hidden or 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 | |
/** | |
* Plugin Name: Restricted Files (All media) | |
* Description: Restrict access to all content from unaothorized users. | |
*/ | |
add_filter( 'vip_files_acl_file_visibility', function ( $file_visibility, $file_path ) { | |
if ( ! is_user_logged_in() ) { | |
return FILE_IS_PRIVATE_AND_DENIED; | |
} | |
$user_has_read_permissions = current_user_can( 'read' ); | |
if ( ! $user_has_read_permissions ) { | |
return FILE_IS_PRIVATE_AND_DENIED; | |
} | |
return FILE_IS_PRIVATE_AND_ALLOWED; | |
}, 10, 2 ); |
This file contains hidden or 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 | |
/** | |
* Plugin Name: Restricted Files (attachement | |
* Description: Restrict access to files/media attached to unpublished content. | |
*/ | |
namespace Automattic\VIP\Files\Acl; | |
const CACHE_GROUP = 'vip-files-acl'; | |
add_filter( 'vip_files_acl_file_visibility', function( $file_visibility, $file_path ) { | |
// Reverse lookup for the attachment ID | |
$attachment_id = get_attachment_id_from_file_path( $file_path ); | |
if ( ! $attachment_id ) { | |
return FILE_NOT_FOUND; | |
} | |
$attachment = get_post( $attachment_id ); | |
if ( ! $attachment ) { | |
return FILE_NOT_FOUND; | |
} | |
if ( 'inherit' === $attachment->post_status && $attachment->post_parent ) { | |
$parent_post = get_post( $attachment->post_parent ); | |
if ( 'publish' === $parent_post->post_status ) { | |
return FILE_IS_PUBLIC; | |
} | |
$user_has_edit_access = current_user_can( 'edit_post', $parent_post ); | |
if ( $user_has_edit_access ) { | |
$file_visibility = FILE_IS_PRIVATE_AND_ALLOWED; | |
} else { | |
$file_visibility = FILE_IS_PRIVATE_AND_DENIED; | |
} | |
} | |
return $file_visibility; | |
}, 10, 3 ); | |
/** | |
* 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. | |
* | |
* @param $path (string) The path to resolve. | |
* | |
* @return (int) The found attachment ID, or 0 on failure. | |
*/ | |
function get_attachment_id_from_file_path( $path ) { | |
global $wpdb; | |
$cache_key = 'path_' . md5( $path ); | |
$attachment_id = wp_cache_get( $cache_key, CACHE_GROUP ); | |
if ( false !== $attachment_id ) { | |
return $attachment_id; | |
} | |
$attachment_id = 0; | |
$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