diff --git a/plugins/woocommerce/includes/abstracts/abstract-wc-product.php b/plugins/woocommerce/includes/abstracts/abstract-wc-product.php index 3dd5352b356..71ffba8a229 100644 --- a/plugins/woocommerce/includes/abstracts/abstract-wc-product.php +++ b/plugins/woocommerce/includes/abstracts/abstract-wc-product.php @@ -1202,7 +1202,7 @@ class WC_Product extends WC_Abstract_Legacy_Product { /** * Set downloads. * - * @throws WC_Data_Exception + * @throws WC_Data_Exception If an error relating to one of the downloads is encountered. * * @param array $downloads_array Array of WC_Product_Download objects or arrays. * diff --git a/plugins/woocommerce/tests/php/includes/class-wc-product-downloads-test.php b/plugins/woocommerce/tests/php/includes/class-wc-product-downloads-test.php index 0cb0ad4dc15..8192a44a069 100644 --- a/plugins/woocommerce/tests/php/includes/class-wc-product-downloads-test.php +++ b/plugins/woocommerce/tests/php/includes/class-wc-product-downloads-test.php @@ -9,7 +9,7 @@ class WC_Product_Download_Test extends WC_Unit_Test_Case { * Test for file without extension. */ public function test_is_allowed_filetype_with_no_extension() { - $upload_dir = trailingslashit( wp_upload_dir()['basedir'] ); + $upload_dir = trailingslashit( wp_upload_dir()['basedir'] ); $file_path_with_no_extension = $upload_dir . 'upload_file'; if ( ! file_exists( $file_path_with_no_extension ) ) { // Copy an existing file without extension. @@ -24,7 +24,7 @@ class WC_Product_Download_Test extends WC_Unit_Test_Case { * Simulates test condition for windows when filename ends with a period. */ public function test_is_allowed_filetype_on_windows_with_period_at_end() { - $upload_dir = trailingslashit( wp_upload_dir()['basedir'] ); + $upload_dir = trailingslashit( wp_upload_dir()['basedir'] ); $file_path_with_period_at_end = $upload_dir . 'upload_file.'; if ( ! file_exists( $file_path_with_period_at_end ) ) { // Copy an existing file without extension. @@ -45,8 +45,20 @@ class WC_Product_Download_Test extends WC_Unit_Test_Case { $download_directories = wc_get_container()->get( Download_Directories::class ); $download_directories->set_mode( Download_Directories::MODE_ENABLED ); - $non_admin_user = wp_insert_user( array( 'user_login' => uniqid(), 'role' => 'editor', 'user_pass' => 'x' ) ); - $admin_user = wp_insert_user( array( 'user_login' => uniqid(), 'role' => 'administrator', 'user_pass' => 'x' ) ); + $non_admin_user = wp_insert_user( + array( + 'user_login' => uniqid(), + 'role' => 'editor', + 'user_pass' => 'x', + ) + ); + $admin_user = wp_insert_user( + array( + 'user_login' => uniqid(), + 'role' => 'administrator', + 'user_pass' => 'x', + ) + ); $ebook_url = 'https://external.site/books/ultimate-guide-to-stuff.pdf'; $podcast_url = 'https://external.site/podcasts/ultimate-guide-to-stuff.mp3'; @@ -63,4 +75,57 @@ class WC_Product_Download_Test extends WC_Unit_Test_Case { $this->expectExceptionMessage( 'cannot be used: it is not located in an approved directory' ); $download->check_is_valid(); } + + /** + * Test handling of filepaths described via shortcodes in relation to the Approved Download Directory + * feature. This is to simulate scenarios such as encountered when using the S3 Downloads extension. + */ + public function test_shortcode_resolution_for_approved_directory_rules() { + /** @var Download_Directories $download_directories */ + $download_directories = wc_get_container()->get( Download_Directories::class ); + $download_directories->set_mode( Download_Directories::MODE_ENABLED ); + $dynamic_filepath = 'https://fast.reliable.external.fileserver.com/bucket-123/textbook.pdf'; + + // We select an admin user because we wish to automatically add Approved Directory rules. + $admin_user = wp_insert_user( + array( + 'user_login' => uniqid(), + 'role' => 'administrator', + 'user_pass' => 'x', + ) + ); + wp_set_current_user( $admin_user ); + + add_shortcode( + 'dynamic-download', + function () { + return 'https://fast.reliable.external.fileserver.com/bucket-123/textbook.pdf'; + } + ); + + $this->assertFalse( + $download_directories->is_valid_path( $dynamic_filepath ), + 'Confirm the filepath returned by the test URL is not yet valid.' + ); + + $download = new WC_Product_Download(); + $download->set_file( '[dynamic-download]' ); + + $this->assertNull( + $download->check_is_valid(), + 'The downloadable file successfully validates (if it did not, an exception would be thrown).' + ); + + $this->assertTrue( + $download_directories->is_valid_path( $dynamic_filepath ), + 'Confirm the filepath returned by the test URL is now considered valid.' + ); + + remove_shortcode( 'dynamic-download' ); + + // Now the shortcode is removed (perhaps the parent plugin has been removed/disabled) it will not resolve + // and so the filepath will not validate. + $this->expectException( 'Error' ); + $download_directories->check_is_valid(); + } }