Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions src/Assets/Asset.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,28 +78,28 @@ class Asset {
protected array $groups = [];

/**
* Should the asset be loaded in the footer?
* Whether the asset be loaded in the footer.
*
* @var bool
*/
protected bool $in_footer = true;

/**
* Should the asset be marked as async?
* Whether the asset be marked as async.
*
* @var bool
*/
protected bool $is_async = false;

/**
* Should the asset be marked as deferred?
* Whether the asset be marked as deferred.
*
* @var bool
*/
protected bool $is_deferred = false;

/**
* Is the asset enqueued?
* Whether the asset has been enqueued.
*
* @var bool
*/
Expand All @@ -113,21 +113,21 @@ class Asset {
protected bool $is_module = false;

/**
* Is the asset printed?
* Whether the asset has been printed.
*
* @var bool
*/
protected bool $is_printed = false;

/**
* Is the asset registered?
* Whether the asset has been registered.
*
* @var bool
*/
protected bool $is_registered = false;

/**
* Is the asset a vendor asset?
* Whether this is a vendor asset.
*
* @var bool
*/
Expand Down Expand Up @@ -534,7 +534,7 @@ protected function build_asset_url(): string {
$url = $plugin_base_url . $resource_path . $resource;

/**
* Filters the asset URL
* Filters the asset URL.
*
* @param string $url Asset URL.
* @param string $slug Asset slug.
Expand Down Expand Up @@ -681,11 +681,11 @@ public function clone_to( string $clone_type, ...$dependencies ) {
$source_type = $this->get_type();

if ( $clone_type === $source_type ) {
throw new \InvalidArgumentException( 'The clone type must be different from the source type.' );
throw new InvalidArgumentException( 'The clone type must be different from the source type.' );
}

if ( ! in_array( $clone_type, [ 'css', 'js' ], true ) ) {
throw new \InvalidArgumentException( 'The clone type must be either "css" or "js".' );
throw new InvalidArgumentException( 'The clone type must be either "css" or "js".' );
}

$slug = $this->slug;
Expand Down
250 changes: 250 additions & 0 deletions src/Assets/VendorAsset.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
<?php

declare( strict_types=1 );

namespace StellarWP\Assets;

use InvalidArgumentException;
use LogicException;

class VendorAsset extends Asset {

/**
* Whether this is a vendor asset.
*
* @var bool
*/
protected bool $is_vendor = true;

/**
* Whether to attempt to load an .asset.php file.
*
* @var bool
*/
protected bool $use_asset_file = false;

/**
* VendorAsset constructor.
*
* @param string $slug The asset slug.
* @param string $url The asset URL.
* @param string $type The asset type.
*
* @throws InvalidArgumentException If the URL is not valid.
*/
public function __construct( string $slug, string $url, string $type = 'js' ) {
$filtered = filter_var( $url, FILTER_VALIDATE_URL );
if ( false === $filtered ) {
throw new InvalidArgumentException( 'The URL must be a valid URL.' );
}

$this->url = $filtered;
$this->slug = sanitize_key( $slug );
$this->type = strtolower( $type );
}

/**
* Set the asset version.
*
* @param string $version The asset version.
*
* @return $this
*/
public function set_version( string $version ): self {
$this->version = $version;
return $this;
}

/**
* Get the asset version.
*
* @since 1.0.0
*
* @return string The asset version.
*/
public function get_version(): string {
return $this->version ?? '';
}

/**
* Get the asset url.
*
* If the version has been provided, then it will be used to format the URL.
*
* @since 1.0.0
*
* @param bool $_unused (Unused) Use the minified version of the asset if available.
*
* @return string
* @throws LogicException If the URL has a placeholder but no version is provided.
*/
public function get_url( bool $_unused = true ): string {
$has_version = null !== $this->version;
if ( ! $has_version && $this->url_has_placeholder( $this->url ) ) {
throw new LogicException( 'A URL with a placeholder must have a version provided.' );
}

$url = $has_version
? $this->get_formatted_url()
: $this->url;

$hook_prefix = Config::get_hook_prefix();

/**
* Filters the asset URL.
*
* @param string $url Asset URL.
* @param string $slug Asset slug.
* @param Asset $asset The Asset object.
*/
return (string) apply_filters( "stellarwp/assets/{$hook_prefix}/resource_url", $url, $this->slug, $this );
}

/**
* Get the minified version of the URL.
*
* @return string
*/
public function get_min_url(): string {
return $this->get_url();
}

/**
* Get the formatted version of the URL.
*
* This will replace the version placeholder in the URL with the actual version. If there
* is no placeholder, it will append the version as a query string.
*
* @return string
*/
protected function get_formatted_url() {
return $this->url_has_placeholder( $this->url )
? sprintf( $this->url, $this->version )
: add_query_arg( 'ver', $this->version, $this->url );
}

/**
* Determine if the URL has a placeholder for the version.
*
* @param string $url The URL to check.
*
* @return bool True if the URL has a placeholder, false otherwise.
*/
protected function url_has_placeholder( string $url ): bool {
return false !== strpos( $url, '%s' );
}

// ---------------------------------------------
// NO-OP or UNUSED METHODS
// ---------------------------------------------

/**
* Get the asset asset file path.
*
* @return string
*/
public function get_asset_file_path(): string {
return '';
}

/**
* Get the asset file.
*
* @return string
*/
public function get_file(): string {
return '';
}

/**
* Get the asset min path.
*
* @return string
*/
public function get_min_path(): string {
return '';
}

/**
* Get the asset min path.
*
* @return string
*/
public function get_path(): string {
return '';
}

/**
* Gets the root path for the resource.
*
* @return ?string
*/
public function get_root_path(): ?string {
return '';
}

/**
* Get the asset translation path.
*
* @return string
*/
public function get_translation_path(): string {
return '';
}

/**
* Get the asset's full path - considering if minified exists.
*
* @param bool $_unused
*
* @return string
*/
public function get_full_resource_path( bool $_unused = true ): string {
return $this->get_url( $_unused );
}

/**
* Set the asset file path for the asset.
*
* @param string $path The partial path to the asset.
*
* @return static
*/
public function set_asset_file( string $path ) {
return $this;
}

/**
* Set the directory where asset should be retrieved.
*
* @param ?string $path The path to the minified file.
* @param ?bool $prefix Whether to prefix files automatically by type (e.g. js/ for JS). Defaults to true.
*
* @return $this
*/
public function set_path( ?string $path = null, $prefix = null ) {
return $this;
}

/**
* Set the directory where min files should be retrieved.
*
* @param ?string $path The path to the minified file.
*
* @return $this
*/
public function set_min_path( ?string $path = null ) {
return $this;
}

/**
* Set whether or not to use an .asset.php file.
*
* @param boolean $_unused Whether to use an .asset.php file.
*
* @return self
*/
public function use_asset_file( bool $_unused = true ): self {
return $this;
}
}
67 changes: 67 additions & 0 deletions tests/wpunit/VendorAssetTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare( strict_types=1 );

namespace wpunit;

use InvalidArgumentException;
use LogicException;
use StellarWP\Assets\Config;
use StellarWP\Assets\Tests\AssetTestCase;
use StellarWP\Assets\VendorAsset;

class VendorAssetTest extends AssetTestCase {

/**
* @before
*/
public function before_tests(): void {
Config::reset();
Config::set_hook_prefix( 'jpry' );
}

public function test_can_create_vendor_asset(): void {
$asset = new VendorAsset( 'test-script', 'https://example.com/fake.js' );

$this->assertEquals( 'test-script', $asset->get_slug() );
$this->assertEquals( 'https://example.com/fake.js', $asset->get_url() );
$this->assertEquals( 'js', $asset->get_type() );
}

public function test_invalid_url_throws_exception(): void {
$this->expectException( InvalidArgumentException::class );

new VendorAsset( 'test-script', 'invalid-url' );
}

public function test_can_set_version(): void {
$asset = new VendorAsset( 'test-script', 'https://example.com/fake.js' );
$asset->set_version( '1.0.0' );

$this->assertEquals( '1.0.0', $asset->get_version() );
$this->assertEquals( 'https://example.com/fake.js?ver=1.0.0', $asset->get_url() );
}

public function test_can_set_version_with_url_placeholder(): void {
$asset = new VendorAsset( 'test-script', 'https://example.com/path/to/version/%s/fake.js' );
$asset->set_version( '1.2.3' );
$this->assertEquals( '1.2.3', $asset->get_version() );
$this->assertEquals( 'https://example.com/path/to/version/1.2.3/fake.js', $asset->get_url() );
}

public function test_placeholder_without_version_throws_error(): void {
$this->expectException( LogicException::class );
$this->expectExceptionMessage( 'A URL with a placeholder must have a version provided.' );

$asset = new VendorAsset( 'test-script', 'https://example.com/path/to/version/%s/fake.js' );
$asset->get_url();
}

public function test_version_with_query_string_has_ver_appended_correctly(): void {
$asset = new VendorAsset( 'test-script', 'https://example.com/path/to/version?query=string' );
$asset->set_version( '1.2.3' );

$this->assertEquals( '1.2.3', $asset->get_version() );
$this->assertEquals( 'https://example.com/path/to/version?query=string&ver=1.2.3', $asset->get_url() );
}
}
Loading