diff --git a/src/wp-includes/link-template.php b/src/wp-includes/link-template.php index 2c80eb3068..555c50949c 100644 --- a/src/wp-includes/link-template.php +++ b/src/wp-includes/link-template.php @@ -930,7 +930,7 @@ function get_edit_term_link( $term_id, $taxonomy = '', $object_type = '' ) { } $tax = get_taxonomy( $term->taxonomy ); - if ( ! $tax || ! current_user_can( $tax->cap->edit_terms ) ) { + if ( ! $tax || ! current_user_can( 'edit_term', $term->term_id ) ) { return; } @@ -984,8 +984,9 @@ function edit_term_link( $link = '', $before = '', $after = '', $term = null, $e return; $tax = get_taxonomy( $term->taxonomy ); - if ( ! current_user_can( $tax->cap->edit_terms ) ) + if ( ! current_user_can( 'edit_term', $term->term_id ) ) { return; + } if ( empty( $link ) ) $link = __('Edit This'); @@ -4023,3 +4024,125 @@ function get_avatar_data( $id_or_email, $args = null ) { */ return apply_filters( 'get_avatar_data', $args, $id_or_email ); } + +/** + * Retrieve the URL of a file in the theme. + * + * Searches in the stylesheet directory before the template directory so themes + * which inherit from a parent theme can just override one file. + * + * @since 4.7.0 + * + * @param string $file Optional. File to search for in the stylesheet directory. + * @return string The URL of the file. + */ +function get_theme_file_uri( $file = '' ) { + $file = ltrim( $file, '/' ); + + if ( empty( $file ) ) { + $url = get_stylesheet_directory_uri(); + } elseif ( file_exists( get_stylesheet_directory() . '/' . $file ) ) { + $url = get_stylesheet_directory_uri() . '/' . $file; + } else { + $url = get_template_directory_uri() . '/' . $file; + } + + /** + * Filter the URL to a file in the theme. + * + * @since 4.7.0 + * + * @param string $url The file URL. + * @param string $file The requested file to search for. + */ + return apply_filters( 'theme_file_uri', $url, $file ); +} + +/** + * Retrieve the URL of a file in the parent theme. + * + * @since 4.7.0 + * + * @param string $file Optional. File to return the URL for in the template directory. + * @return string The URL of the file. + */ +function get_parent_theme_file_uri( $file = '' ) { + $file = ltrim( $file, '/' ); + + if ( empty( $file ) ) { + $url = get_template_directory_uri(); + } else { + $url = get_template_directory_uri() . '/' . $file; + } + + /** + * Filter the URL to a file in the parent theme. + * + * @since 4.7.0 + * + * @param string $url The file URL. + * @param string $file The requested file to search for. + */ + return apply_filters( 'parent_theme_file_uri', $url, $file ); +} + +/** + * Retrieve the path of a file in the theme. + * + * Searches in the stylesheet directory before the template directory so themes + * which inherit from a parent theme can just override one file. + * + * @since 4.7.0 + * + * @param string $file Optional. File to search for in the stylesheet directory. + * @return string The path of the file. + */ +function get_theme_file_path( $file = '' ) { + $file = ltrim( $file, '/' ); + + if ( empty( $file ) ) { + $path = get_stylesheet_directory(); + } elseif ( file_exists( get_stylesheet_directory() . '/' . $file ) ) { + $path = get_stylesheet_directory() . '/' . $file; + } else { + $path = get_template_directory() . '/' . $file; + } + + /** + * Filter the path to a file in the theme. + * + * @since 4.7.0 + * + * @param string $path The file path. + * @param string $file The requested file to search for. + */ + return apply_filters( 'theme_file_path', $path, $file ); +} + +/** + * Retrieve the path of a file in the parent theme. + * + * @since 4.7.0 + * + * @param string $file Optional. File to return the path for in the template directory. + * @return string The path of the file. + */ +function get_parent_theme_file_path( $file = '' ) { + $file = ltrim( $file, '/' ); + + if ( empty( $file ) ) { + $path = get_template_directory(); + } else { + $path = get_template_directory() . '/' . $file; + } + + /** + * Filter the path to a file in the parent theme. + * + * @since 4.7.0 + * + * @param string $path The file path. + * @param string $file The requested file to search for. + */ + return apply_filters( 'parent_theme_file_path', $path, $file ); +} diff --git a/tests/phpunit/data/theme-file-child/child-only.php b/tests/phpunit/data/theme-file-child/child-only.php new file mode 100644 index 0000000000..9065825c33 --- /dev/null +++ b/tests/phpunit/data/theme-file-child/child-only.php @@ -0,0 +1 @@ + diff --git a/tests/phpunit/data/theme-file-child/parent-and-child.php b/tests/phpunit/data/theme-file-child/parent-and-child.php new file mode 100644 index 0000000000..fb1203accf --- /dev/null +++ b/tests/phpunit/data/theme-file-child/parent-and-child.php @@ -0,0 +1 @@ + diff --git a/tests/phpunit/data/theme-file-child/style.css b/tests/phpunit/data/theme-file-child/style.css new file mode 100644 index 0000000000..2b0e145eda --- /dev/null +++ b/tests/phpunit/data/theme-file-child/style.css @@ -0,0 +1,4 @@ +/* +Theme Name: Child Theme +Template: theme-file-parent +*/ diff --git a/tests/phpunit/data/theme-file-parent/parent-and-child.php b/tests/phpunit/data/theme-file-parent/parent-and-child.php new file mode 100644 index 0000000000..fb1203accf --- /dev/null +++ b/tests/phpunit/data/theme-file-parent/parent-and-child.php @@ -0,0 +1 @@ + diff --git a/tests/phpunit/data/theme-file-parent/parent-only.php b/tests/phpunit/data/theme-file-parent/parent-only.php new file mode 100644 index 0000000000..22a963c4e6 --- /dev/null +++ b/tests/phpunit/data/theme-file-parent/parent-only.php @@ -0,0 +1 @@ + diff --git a/tests/phpunit/data/theme-file-parent/style.css b/tests/phpunit/data/theme-file-parent/style.css new file mode 100644 index 0000000000..418cb056f7 --- /dev/null +++ b/tests/phpunit/data/theme-file-parent/style.css @@ -0,0 +1,3 @@ +/* +Theme Name: Parent Theme +*/ diff --git a/tests/phpunit/tests/link/themeFile.php b/tests/phpunit/tests/link/themeFile.php new file mode 100644 index 0000000000..53408aeab7 --- /dev/null +++ b/tests/phpunit/tests/link/themeFile.php @@ -0,0 +1,146 @@ + +assertSame( content_url( "themes/theme-file-parent/{$file}" ), get_theme_file_uri( $file ) ); + $this->assertSame( content_url( "themes/theme-file-parent/{$file}" ), get_parent_theme_file_uri( $file ) ); + } + + /** + * @ticket 18302 + * + * @dataProvider data_theme_files + */ + public function test_theme_file_uri_with_child_theme( $file, $expected_theme, $existence ) { + switch_theme( 'theme-file-child' ); + + // Ensure the returned URL uses the expected theme: + $this->assertSame( content_url( "themes/{$expected_theme}/{$file}" ), get_theme_file_uri( $file ) ); + + // Ensure the returned URL always uses the parent theme: + $this->assertSame( content_url( "themes/theme-file-parent/{$file}" ), get_parent_theme_file_uri( $file ) ); + } + + /** + * @ticket 18302 + * + * @dataProvider data_theme_files + */ + public function test_theme_file_path_with_parent_theme( $file, $expected_theme, $existence ) { + switch_theme( 'theme-file-parent' ); + + // Ensure the returned path always uses the parent theme: + $this->assertSame( WP_CONTENT_DIR . "/themes/theme-file-parent/{$file}", get_theme_file_path( $file ) ); + $this->assertSame( WP_CONTENT_DIR . "/themes/theme-file-parent/{$file}", get_parent_theme_file_path( $file ) ); + } + + /** + * @ticket 18302 + * + * @dataProvider data_theme_files + */ + public function test_theme_file_path_with_child_theme( $file, $expected_theme, $existence ) { + switch_theme( 'theme-file-child' ); + + // Ensure the returned path uses the expected theme: + $this->assertSame( WP_CONTENT_DIR . "/themes/{$expected_theme}/{$file}", get_theme_file_path( $file ) ); + + // Ensure the returned path always uses the parent theme: + $this->assertSame( WP_CONTENT_DIR . "/themes/theme-file-parent/{$file}", get_parent_theme_file_path( $file ) ); + } + + /** + * Test the tests. + * + * @ticket 18302 + * + * @dataProvider data_theme_files + */ + public function test_theme_file_existance( $file, $expected_theme, $existence ) { + + if ( in_array( 'theme-file-child', $existence, true ) ) { + $this->assertFileExists( WP_CONTENT_DIR . "/themes/theme-file-child/{$file}" ); + } else { + $this->assertFileNotExists( WP_CONTENT_DIR . "/themes/theme-file-child/{$file}" ); + } + + if ( in_array( 'theme-file-parent', $existence, true ) ) { + $this->assertFileExists( WP_CONTENT_DIR . "/themes/theme-file-parent/{$file}" ); + } else { + $this->assertFileNotExists( WP_CONTENT_DIR . "/themes/theme-file-parent/{$file}" ); + } + + } + + /** + * @ticket 18302 + * + * @dataProvider data_theme_files + */ + public function test_theme_file_uri_returns_valid_uri( $file, $expected_theme, $existence ) { + $uri = get_theme_file_uri( $file ); + $parent_uri = get_parent_theme_file_uri( $file ); + + $this->assertSame( esc_url_raw( $uri ), $uri ); + $this->assertSame( esc_url_raw( $parent_uri ), $parent_uri ); + } + + public function data_theme_files() { + $parent = 'theme-file-parent'; + $child = 'theme-file-child'; + + return array( + array( + 'parent-only.php', + $parent, + array( + $parent, + ), + ), + array( + 'child-only.php', + $child, + array( + $child, + ), + ), + array( + 'parent-and-child.php', + $child, + array( + $parent, + $child, + ), + ), + array( + 'neither.php', + $parent, + array( + ), + ), + ); + } + +}