diff --git a/docs/Asset-Loading.md b/docs/Asset-Loading.md index a37b67b..f8606dc 100644 --- a/docs/Asset-Loading.md +++ b/docs/Asset-Loading.md @@ -1,7 +1,16 @@ # Asset Loading ## Overview -Use the `TenupFramework\Assets\GetAssetInfo` trait to read dependency and version metadata generated by your build (the `.asset.php` sidecar files). The trait looks for files in: +Use the `TenupFramework\Assets\GetAssetInfo` trait to read dependency and version metadata generated by your build (the `.asset.php` sidecar files). The trait supports two approaches for locating asset files: + +### Prefix-based paths (recommended) +When you specify a prefix in the slug, the trait looks for files directly in the corresponding subdirectory: +- `get_asset_info('css/admin')` → `dist/css/admin.asset.php` +- `get_asset_info('js/admin')` → `dist/js/admin.asset.php` +- `get_asset_info('blocks/my-block')` → `dist/blocks/my-block.asset.php` + +### Fallback behavior +For slugs without prefixes, the trait searches in this order: - `dist/js/{slug}.asset.php` - `dist/css/{slug}.asset.php` - `dist/blocks/{slug}.asset.php` @@ -55,6 +64,19 @@ Notes: - If your build produces multiple variants (e.g., `admin.js` vs `admin.min.js`), you can conditionally enqueue based on `SCRIPT_DEBUG` or `wp_get_environment_type() === 'development'`. ## Enqueuing scripts + +### Using prefix-based paths (recommended) +```php +wp_enqueue_script( + 'tenup_plugin_admin', + YOUR_PLUGIN_URL . 'dist/js/admin.js', + $this->get_asset_info( 'js/admin', 'dependencies' ), + $this->get_asset_info( 'js/admin', 'version' ), + true +); +``` + +### Using fallback behavior ```php wp_enqueue_script( 'tenup_plugin_admin', @@ -68,6 +90,18 @@ wp_enqueue_script( - version: string used for cache busting ## Enqueuing styles + +### Using prefix-based paths (recommended) +```php +wp_enqueue_style( + 'tenup_plugin_admin', + YOUR_PLUGIN_URL . 'dist/css/admin.css', + [], // CSS dependencies are uncommon; pass [] unless needed + $this->get_asset_info( 'css/admin', 'version' ) +); +``` + +### Using fallback behavior ```php wp_enqueue_style( 'tenup_plugin_admin', @@ -78,7 +112,17 @@ wp_enqueue_style( ``` ## Working with blocks -If you build blocks, pass the block slug used by your build tool: + +### Using prefix-based paths (recommended) +```php +$deps = $this->get_asset_info( 'blocks/my-block', 'dependencies' ); +$ver = $this->get_asset_info( 'blocks/my-block', 'version' ); +$handle = 'tenup_my_block'; + +wp_register_script( $handle, YOUR_PLUGIN_URL . 'dist/blocks/my-block.js', $deps, $ver, true ); +``` + +### Using fallback behavior ```php $deps = $this->get_asset_info( 'my-block', 'dependencies' ); $ver = $this->get_asset_info( 'my-block', 'version' ); @@ -88,6 +132,21 @@ wp_register_script( $handle, YOUR_PLUGIN_URL . 'dist/blocks/my-block.js', $deps, ``` The trait automatically checks `dist/blocks/my-block.asset.php` if present. +## Resolving asset conflicts + +When you have JS and CSS assets with the same handle (e.g., both `admin.js` and `admin.css`), use prefix-based paths to avoid conflicts: + +```php +// ❌ Problematic: Both would load the same asset data +$this->get_asset_info( 'admin', 'dependencies' ); // Could load JS instead of CSS data if both CSS and JS files exist with the same name. + +// ✅ Recommended: Explicitly specify the asset type +$this->get_asset_info( 'js/admin', 'dependencies' ); // Always loads JS asset data +$this->get_asset_info( 'css/admin', 'dependencies' ); // Always loads CSS asset data +``` + +This ensures that each asset type gets its correct dependencies and version information. + ## Error handling and fallbacks ```php try { @@ -105,6 +164,8 @@ try { - Keep your dist path stable across environments (use constants for PATH and URL). - Use the version from `.asset.php` for reliable cache busting in production. - For admin-only assets, enqueue on `admin_enqueue_scripts`; for frontend, use `wp_enqueue_scripts`. +- **Use prefix-based paths** (`'js/admin'`, `'css/admin'`, `'blocks/my-block'`) to avoid conflicts when you have assets with the same handle across different types. +- Prefix-based paths are **backwards compatible** - existing code using fallback behavior will continue to work. ## See also - [Docs Home](README.md) diff --git a/fixtures/assets/dist/blocks/test-block.asset.php b/fixtures/assets/dist/blocks/test-block.asset.php new file mode 100644 index 0000000..abdc30f --- /dev/null +++ b/fixtures/assets/dist/blocks/test-block.asset.php @@ -0,0 +1 @@ + array( 'test-block-deps' ), 'version' => 'test-block-version'); diff --git a/src/Assets/GetAssetInfo.php b/src/Assets/GetAssetInfo.php index f2d13a3..ef24266 100644 --- a/src/Assets/GetAssetInfo.php +++ b/src/Assets/GetAssetInfo.php @@ -59,7 +59,9 @@ public function get_asset_info( string $slug, ?string $attribute = null ): strin throw new RuntimeException( 'Asset variables not set. Please run setup_asset_vars() before calling get_asset_info().' ); } - if ( file_exists( $this->dist_path . 'js/' . $slug . '.asset.php' ) ) { + if ( file_exists( $this->dist_path . $slug . '.asset.php' ) ) { + $asset = require $this->dist_path . $slug . '.asset.php'; + } elseif ( file_exists( $this->dist_path . 'js/' . $slug . '.asset.php' ) ) { $asset = require $this->dist_path . 'js/' . $slug . '.asset.php'; } elseif ( file_exists( $this->dist_path . 'css/' . $slug . '.asset.php' ) ) { $asset = require $this->dist_path . 'css/' . $slug . '.asset.php'; diff --git a/tests/Assets/GetAssetInfoTest.php b/tests/Assets/GetAssetInfoTest.php index d08139f..415772f 100644 --- a/tests/Assets/GetAssetInfoTest.php +++ b/tests/Assets/GetAssetInfoTest.php @@ -130,4 +130,117 @@ public function test_get_asset_info_throws_exception_when_called_without_setting slug: 'test-script' ); } + + /** + * Test get_asset_info with prefix-based slug handling (css/, js/, blocks/). + * + * @return void + */ + public function test_get_asset_info_with_prefix_based_slug() { + $asset_info = new class() { + use GetAssetInfo; + }; + + $asset_info->setup_asset_vars( + dist_path: dirname( __DIR__, 2 ) . '/fixtures/assets/dist', + fallback_version: '1.0.0' + ); + + // Test CSS prefix with existing fixture + $asset = $asset_info->get_asset_info( slug: 'css/test-style' ); + $this->assertIsArray( $asset ); + $this->assertArrayHasKey( 'version', $asset ); + $this->assertArrayHasKey( 'dependencies', $asset ); + $vars = require dirname( __DIR__, 2 ) . '/fixtures/assets/dist/css/test-style.asset.php'; + $this->assertEquals( $vars, $asset ); + + // Test JS prefix with existing fixture + $asset = $asset_info->get_asset_info( slug: 'js/test-script' ); + $this->assertIsArray( $asset ); + $this->assertArrayHasKey( 'version', $asset ); + $this->assertArrayHasKey( 'dependencies', $asset ); + $vars = require dirname( __DIR__, 2 ) . '/fixtures/assets/dist/js/test-script.asset.php'; + $this->assertEquals( $vars, $asset ); + + // Test blocks prefix with existing fixture + $asset = $asset_info->get_asset_info( slug: 'blocks/test-block' ); + $this->assertIsArray( $asset ); + $this->assertArrayHasKey( 'version', $asset ); + $this->assertArrayHasKey( 'dependencies', $asset ); + $vars = require dirname( __DIR__, 2 ) . '/fixtures/assets/dist/blocks/test-block.asset.php'; + $this->assertEquals( $vars, $asset ); + } + + /** + * Test get_asset_info priority order: prefix-based slugs take priority over fallback. + * + * @return void + */ + public function test_get_asset_info_priority_order_prefix_vs_fallback() { + $asset_info = new class() { + use GetAssetInfo; + }; + + $asset_info->setup_asset_vars( + dist_path: dirname( __DIR__, 2 ) . '/fixtures/assets/dist', + fallback_version: '1.0.0' + ); + + // Test that prefix-based slug works with existing fixtures + $asset = $asset_info->get_asset_info( slug: 'css/test-style' ); + $this->assertIsArray( $asset ); + $this->assertArrayHasKey( 'version', $asset ); + $this->assertArrayHasKey( 'dependencies', $asset ); + $vars = require dirname( __DIR__, 2 ) . '/fixtures/assets/dist/css/test-style.asset.php'; + $this->assertEquals( $vars, $asset ); + + // Test that fallback still works for non-prefixed slugs + $asset = $asset_info->get_asset_info( slug: 'test-script' ); + $this->assertIsArray( $asset ); + $this->assertArrayHasKey( 'version', $asset ); + $this->assertArrayHasKey( 'dependencies', $asset ); + $vars = require dirname( __DIR__, 2 ) . '/fixtures/assets/dist/js/test-script.asset.php'; + $this->assertEquals( $vars, $asset ); + } + + /** + * Test get_asset_info fallback behavior when direct file doesn't exist. + * + * @return void + */ + public function test_get_asset_info_fallback_when_direct_file_missing() { + $asset_info = new class() { + use GetAssetInfo; + }; + + $asset_info->setup_asset_vars( + dist_path: dirname( __DIR__, 2 ) . '/fixtures/assets/dist', + fallback_version: '1.0.0' + ); + + // Test that it falls back to JS directory first (priority order: js -> css -> blocks) + // Using existing fixture that exists in js/ directory + $asset = $asset_info->get_asset_info( slug: 'test-script' ); + $this->assertIsArray( $asset ); + $this->assertArrayHasKey( 'version', $asset ); + $this->assertArrayHasKey( 'dependencies', $asset ); + $vars = require dirname( __DIR__, 2 ) . '/fixtures/assets/dist/js/test-script.asset.php'; + $this->assertEquals( $vars, $asset ); + + // Test CSS fallback with existing fixture + $asset = $asset_info->get_asset_info( slug: 'test-style' ); + $this->assertIsArray( $asset ); + $this->assertArrayHasKey( 'version', $asset ); + $this->assertArrayHasKey( 'dependencies', $asset ); + $vars = require dirname( __DIR__, 2 ) . '/fixtures/assets/dist/css/test-style.asset.php'; + $this->assertEquals( $vars, $asset ); + + // Test blocks fallback with existing fixture + $asset = $asset_info->get_asset_info( slug: 'test-block' ); + $this->assertIsArray( $asset ); + $this->assertArrayHasKey( 'version', $asset ); + $this->assertArrayHasKey( 'dependencies', $asset ); + $vars = require dirname( __DIR__, 2 ) . '/fixtures/assets/dist/blocks/test-block.asset.php'; + $this->assertEquals( $vars, $asset ); + } }