diff --git a/assets.php b/assets.php index e6d15fb..6ba87e2 100644 --- a/assets.php +++ b/assets.php @@ -2,7 +2,7 @@ /** * Plugin Name: Assets * Description: Asset library with a plugin bootstrap file for automated testing. - * Version: 1.0.0 + * Version: 1.2.3 * Author: StellarWP * Author URI: https://stellarwp.com */ diff --git a/src/Assets/Asset.php b/src/Assets/Asset.php index 89346d4..52bcc5a 100644 --- a/src/Assets/Asset.php +++ b/src/Assets/Asset.php @@ -849,61 +849,34 @@ public function is_vendor(): bool { * @return string|false The url to the minified version or false, if file not found. */ public function maybe_get_min_file( $url ) { - static $wpmu_plugin_url; - static $wp_plugin_url; - static $wp_content_url; - static $plugins_url; - static $base_dirs; - static $stylesheet_url; - static $stylesheet_dir; + $bases = Utils::get_bases(); $urls = []; - if ( ! isset( $wpmu_plugin_url ) ) { - $wpmu_plugin_url = set_url_scheme( WPMU_PLUGIN_URL ); - } - - if ( ! isset( $wp_plugin_url ) ) { - $wp_plugin_url = set_url_scheme( WP_PLUGIN_URL ); - } - - if ( ! isset( $wp_content_url ) ) { - $wp_content_url = set_url_scheme( WP_CONTENT_URL ); - } - if ( ! isset( $plugins_url ) ) { - $plugins_url = plugins_url(); - } - - if ( ! isset( $stylesheet_url ) ) { - $stylesheet_url = get_stylesheet_directory_uri(); - $stylesheet_dir = get_stylesheet_directory(); - } - - if ( ! isset( $base_dirs ) ) { - $base_dirs[ WPMU_PLUGIN_DIR ] = wp_normalize_path( WPMU_PLUGIN_DIR ); - $base_dirs[ WP_PLUGIN_DIR ] = wp_normalize_path( WP_PLUGIN_DIR ); - $base_dirs[ WP_CONTENT_DIR ] = wp_normalize_path( WP_CONTENT_DIR ); - $base_dirs[ $stylesheet_dir ] = wp_normalize_path( $stylesheet_dir ); - } + $wpmu_plugin_url = $bases['wpmu_plugin']['base_url']; + $wp_plugin_url = $bases['wp_plugin']['base_url']; + $wp_content_url = $bases['wp_content']['base_url']; + $plugins_url = $bases['plugins']['base_url']; + $stylesheet_url = $bases['stylesheet']['base_url']; if ( 0 === strpos( $url, $wpmu_plugin_url ) ) { // URL inside WPMU plugin dir. - $base_dir = $base_dirs[ WPMU_PLUGIN_DIR ]; - $base_url = $wpmu_plugin_url; + $base_dir = $bases['wpmu_plugin']['base_dir']; + $base_url = $bases['wpmu_plugin']['base_url']; } elseif ( 0 === strpos( $url, $wp_plugin_url ) ) { // URL inside WP plugin dir. - $base_dir = $base_dirs[ WP_PLUGIN_DIR ]; - $base_url = $wp_plugin_url; + $base_dir = $bases['wp_plugin']['base_dir']; + $base_url = $bases['wp_plugin']['base_url']; } elseif ( 0 === strpos( $url, $wp_content_url ) ) { // URL inside WP content dir. - $base_dir = $base_dirs[ WP_CONTENT_DIR ]; - $base_url = $wp_content_url; + $base_dir = $bases['wp_content']['base_dir']; + $base_url = $bases['wp_content']['base_url']; } elseif ( 0 === strpos( $url, $plugins_url ) ) { - $base_dir = $base_dirs[ WP_PLUGIN_DIR ]; - $base_url = $plugins_url; + $base_dir = $bases['plugins']['base_dir']; + $base_url = $bases['plugins']['base_url']; } elseif ( 0 === strpos( $url, $stylesheet_url ) ) { - $base_dir = $base_dirs[ $stylesheet_dir ]; - $base_url = $stylesheet_url; + $base_dir = $bases['stylesheet']['base_dir']; + $base_url = $bases['stylesheet']['base_url']; } else { // Resource needs to be inside wp-content or a plugins dir. return false; diff --git a/src/Assets/Assets.php b/src/Assets/Assets.php index 018c9d8..dbefe32 100755 --- a/src/Assets/Assets.php +++ b/src/Assets/Assets.php @@ -674,11 +674,11 @@ protected function do_enqueue( Asset $asset, bool $force_enqueue = false ): void /** * Register the Assets on the correct hooks. * + * @since 1.0.0 + * * @param array|Asset|null $assets Array of asset objects, single asset object, or null. * * @return void - * @since 1.0.0 - * */ public function register_in_wp( $assets = null ) { if ( ! ( @@ -775,11 +775,11 @@ public function register_in_wp( $assets = null ) { /** * Removes an Asset from been registered and enqueue. * + * @since 1.0.0 + * * @param string $slug Slug of the Asset. * * @return bool - * @since 1.0.0 - * */ public function remove( $slug ) { if ( ! $this->exists( $slug ) ) { @@ -806,13 +806,13 @@ public function remove( $slug ) { * * The method will force the scripts and styles to print overriding their registration and conditional. * + * @since 1.0.0 + * * @param string|array $group Which group(s) should be enqueued. * @param bool $echo Whether to print the group(s) tag(s) to the page or not; default to `true` to * print the HTML `script` (JS) and `link` (CSS) tags to the page. * * @return string The `script` and `link` HTML tags produced for the group(s). - * @since 1.0.0 - * */ public function print_group( $group, $echo = true ) { $all_assets = $this->get(); diff --git a/src/Assets/Config.php b/src/Assets/Config.php index 2c521a2..43be86b 100644 --- a/src/Assets/Config.php +++ b/src/Assets/Config.php @@ -70,11 +70,14 @@ public static function get_relative_asset_path(): string { * @return string */ public static function get_url( $path ): string { - if ( empty( static::$path_urls[ $path ] ) ) { - static::$path_urls[ $path ] = trailingslashit( get_site_url() . $path ); + $key = Utils::get_runtime_cache_key( [ $path ] ); + + if ( empty( static::$path_urls[ $key ] ) ) { + $bases = Utils::get_bases(); + static::$path_urls[ $key ] = trailingslashit( str_replace( wp_list_pluck( $bases, 'base_dir' ), wp_list_pluck( $bases, 'base_url' ), $path ) ); } - return static::$path_urls[ $path ]; + return static::$path_urls[ $key ]; } /** @@ -127,17 +130,15 @@ public static function set_relative_asset_path( string $path ) { * @return void */ public static function set_path( string $path ) { - $content_dir = str_replace( get_site_url(), '', WP_CONTENT_URL ); - - $plugins_content_dir_position = strpos( $path, $content_dir . '/plugins' ); - $themes_content_dir_position = strpos( $path, $content_dir . '/themes' ); + $plugins_content_dir_position = strpos( $path, WP_PLUGIN_DIR ); + $themes_content_dir_position = strpos( $path, get_theme_root() ); if ( $plugins_content_dir_position === false && $themes_content_dir_position === false ) { // Default to plugins. - $path = $content_dir . '/plugins/' . $path; + $path = WP_PLUGIN_DIR . $path; } elseif ( $plugins_content_dir_position !== false ) { $path = substr( $path, $plugins_content_dir_position ); } elseif ( $themes_content_dir_position !== false ) { diff --git a/src/Assets/Utils.php b/src/Assets/Utils.php index 050f451..b0c4ff3 100644 --- a/src/Assets/Utils.php +++ b/src/Assets/Utils.php @@ -3,6 +3,15 @@ namespace StellarWP\Assets; class Utils { + /** + * Stores all the Bases for the request. + * + * @since 1.2.3 + * + * @var array + */ + protected static array $bases = []; + /** * Determines if the provided value should be regarded as 'true'. * @@ -53,4 +62,72 @@ public static function is_truthy( $var ) : bool { // For other types (ints, floats etc) cast to bool return (bool) $var; } + + /** + * Gets the asset bases for the request, both directory and URL. + * + * @since 1.2.3 + * + * @return array + */ + public static function get_bases(): array { + $key = self::get_runtime_cache_key(); + + if ( empty( static::$bases[ $key ] ) ) { + static::$bases[ $key ] = [ + 'wpmu_plugin' => [ + 'base_dir' => wp_normalize_path( WPMU_PLUGIN_DIR ), + 'base_url' => set_url_scheme( WPMU_PLUGIN_URL ), + ], + 'wp_plugin' => [ + 'base_dir' => wp_normalize_path( WP_PLUGIN_DIR ), + 'base_url' => set_url_scheme( WP_PLUGIN_URL ), + ], + 'wp_content' => [ + 'base_dir' => wp_normalize_path( WP_CONTENT_DIR ), + 'base_url' => set_url_scheme( WP_CONTENT_URL ), + ], + 'plugins' => [ + 'base_dir' => wp_normalize_path( WP_PLUGIN_DIR ), + 'base_url' => plugins_url(), + ], + 'stylesheet' => [ + 'base_dir' => wp_normalize_path( get_stylesheet_directory() ), + 'base_url' => get_stylesheet_directory_uri(), + ], + ]; + } + + return static::$bases[ $key ]; + } + + /** + * Get the runtime cache key. + * + * @since 1.2.3 + * + * @param array $extra Extra data to include in the cache key. + * + * @return string + */ + public static function get_runtime_cache_key( array $extra = [] ): string { + return md5( + serialize( + array_merge( + [ + WPMU_PLUGIN_DIR, + WPMU_PLUGIN_URL, + WP_PLUGIN_DIR, + WP_PLUGIN_URL, + WP_CONTENT_DIR, + WP_CONTENT_URL, + plugins_url(), + get_stylesheet_directory(), + get_stylesheet_directory_uri(), + ], + $extra + ) + ) + ); + } } diff --git a/tests/wpunit/AssetsTest.php b/tests/wpunit/AssetsTest.php index 9c2d638..42eb2a0 100644 --- a/tests/wpunit/AssetsTest.php +++ b/tests/wpunit/AssetsTest.php @@ -77,6 +77,85 @@ public function it_should_locate_minified_versions_of_external_assets() { } } + /** + * @test + * + * @dataProvider constantProvider + */ + public function it_should_get_the_correct_url_when_wp_content_dir_and_wp_content_url_are_diff( $id, $constants ) { + $slugs = [ + 'fake1' => [ true, false ], + 'fake2' => [ false, false ], + 'fake3' => [ true, true ] + ]; + + foreach ( array_keys( $slugs ) as $slug ) { + Assets::init()->remove( $slug . '-script' ); + Assets::init()->remove( $slug . '-style' ); + } + + foreach ( $constants as $constant => $value ) { + $this->set_const_value( $constant, $value ); + $this->assertEquals( $value, constant( $constant ) ); + } + + Config::reset(); + + Config::set_hook_prefix( 'bork' ); + Config::set_version( '1.1.0' ); + Config::set_path( constant( 'WP_PLUGIN_DIR' ) . '/assets' ); + Config::set_relative_asset_path( 'tests/_data/' ); + + foreach ( array_keys( $slugs ) as $slug ) { + Asset::add( $slug . '-script', $slug . '.js' ); + Asset::add( $slug . '-style', $slug . '.css' ); + } + + foreach ( $slugs as $slug => $data ) { + $this->assert_minified_found( $slug, true, $data['0'], $data['1'], $id ); + $this->assert_minified_found( $slug, false, $data['0'], $data['1'], $id ); + } + } + + public function constantProvider() { + $data = [ + [ + // Normal. + '**normal**', + [ + 'WP_CONTENT_DIR' => '/var/www/html/wp-content', + 'WP_CONTENT_URL' => 'http://wordpress.test/wp-content', + 'WP_PLUGIN_DIR' => '/var/www/html/wp-content/plugins', + 'WP_PLUGIN_URL' => 'http://wordpress.test/wp-content/plugins', + ], + ], + [ + // Small complexity. + '**small-complex**', + [ + 'WP_CONTENT_DIR' => '/var/www/html/wp-content', + 'WP_CONTENT_URL' => 'http://wordpress.test/foo', + 'WP_PLUGIN_DIR' => '/var/www/html/wp-content/plugins', + 'WP_PLUGIN_URL' => 'http://wordpress.test/foo/plugins', + ], + ], + [ + // Complex. + '**complex**', + [ + 'WP_CONTENT_DIR' => '/var/www/html/content', + 'WP_CONTENT_URL' => 'http://wordpress.test/content', + 'WP_PLUGIN_DIR' => '/var/www/html/plugins', + 'WP_PLUGIN_URL' => 'http://wordpress.test/plugins', + ], + ], + ]; + + foreach ( $data as $d ) { + yield $d; + } + } + /** * @test */ @@ -396,10 +475,10 @@ protected function existence_assertions( $test_slug_prefix ) { * @param bool $has_min * @param bool $has_only_min */ - protected function assert_minified_found( $slug_prefix, $is_js = true, $has_min = true, $has_only_min = false ) { + protected function assert_minified_found( $slug_prefix, $is_js = true, $has_min = true, $has_only_min = false, $id = '' ) { $asset = Assets::init()->get( $slug_prefix . '-' . ( $is_js ? 'script' : 'style' ) ); - $url = get_site_url() . '/wp-content/plugins/assets/tests/_data/' . ( $is_js ? 'js' : 'css' ) . '/' . $slug_prefix; + $url = plugins_url( '/assets/tests/_data/' . ( $is_js ? 'js' : 'css' ) . '/' . $slug_prefix ); $urls = []; @@ -418,9 +497,24 @@ protected function assert_minified_found( $slug_prefix, $is_js = true, $has_min $urls[] = $url . ( $is_js ? '.js' : '.css' ); } + $plugins_path = str_replace( constant( 'WP_CONTENT_DIR' ), '', constant( 'WP_PLUGIN_DIR' ) ); + + if ( constant( 'WP_PLUGIN_DIR' ) !== constant( 'WP_CONTENT_DIR' ) . $plugins_path ) { + // If we are testing outside of the actual plugin directory, the file_exists will always fail. + // In installations where this set up is the actual, the file should exist. + // In this case it will always fail to locate mins. + $urls = array_map( + static function ( $url ) { + return str_replace( '.min', '', $url ); + }, + $urls + ); + } + $this->assertEquals( $urls['0'], - $asset->get_url() + $asset->get_url(), + $id ); $this->set_const_value( 'SCRIPT_DEBUG', true ); @@ -435,7 +529,8 @@ protected function assert_minified_found( $slug_prefix, $is_js = true, $has_min $this->assertEquals( $urls['1'], - $asset->get_url() + $asset->get_url(), + $id ); } diff --git a/tests/wpunit/ConfigTest.php b/tests/wpunit/ConfigTest.php index 871957f..27ba25a 100644 --- a/tests/wpunit/ConfigTest.php +++ b/tests/wpunit/ConfigTest.php @@ -29,7 +29,7 @@ public function should_set_hook_prefix() { public function should_set_path() { Config::set_path( dirname( dirname( __DIR__ ) ) ); - $this->assertEquals( '/wp-content/plugins/assets/', Config::get_path() ); + $this->assertEquals( WP_PLUGIN_DIR . '/assets/', Config::get_path() ); } /**