Skip to content

Commit

Permalink
Candidate 0.3
Browse files Browse the repository at this point in the history
Added:
 - Possibility to obtain the `Collection` of all assets registered/enqueued. This enables the possibility to act on existing assets both individually and collectively
 - Allow deregister and dequeue t be done directly from the Assets class, including for assets not registered/enqueued via the Assets class itself
 - `JsEnqueue::useStrategy()` to allow editing the "in_footer" strategy after registration/enqueue
 - `Collection::append()`, `Collection::remove()`, and Collection::dequeue()
 - Added `Enqueue::deregister()` to the `Enqueue` contract
 - Action hook fired on the registration, internally used to remove the assets from the Collection

Changed:
 - Assets previoulsy registered via WP functions are deregistered to allow new registration via the library
 - Improved tests and more consistency in code styles
  • Loading branch information
gmazzap committed Mar 1, 2024
1 parent a52193b commit 92e49bd
Show file tree
Hide file tree
Showing 13 changed files with 640 additions and 125 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,29 @@ Please review [`Collection` source code](./src/Enqueue/Collection.php) to find o



### Retrieving registered/enqueued assets' collection

The `Assets` class provides a `Assets::collection()` method that returns a `Collection` instance with all the assets that have been enqueued/registered. The collection allows us to act on individual assets (retrieved via `Collection::oneByName()` or `Collection::oneByHandle()`) or collectively on all or some assets (filtered using one of the many methods `Collection` provides, see above).

Here's an example on how this could be leveraged for obtaining "automatic bulk registration" for all our assets in few lines of code that loop files in the assets directory:

```php
$assets = Assets::forTheme('/dist')->useDependencyExtractionData();

foreach (glob($assets->context()->basePath() . '*.{css,js}', GLOB_BRACE) as $file) {
str_ends_with($file, '.css')
? $assets->registerStyle(basename($file, '.css'))
: $assets->registerScript(basename($file, '.js'));
}

add_action('admin_enqueue_scripts'), fn () => $assets->collection()->keep('*-admin')->enqueue());
add_action('wp_enqueue_scripts'), fn () => $assets->collection()->keep('*-view')->enqueue());
```

Please note: because `Collection` has an immutable design, do not store the result of `Assets::collection()` but always call that method to retrieve an up-to-date collection.




### Debug

Expand Down
1 change: 1 addition & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@
<issueHandlers>
<MixedAssignment errorLevel="suppress" />
<RedundantCastGivenDocblockType errorLevel="suppress" />
<RedundantConditionGivenDocblockType errorLevel="suppress" />
</issueHandlers>
</psalm>
161 changes: 146 additions & 15 deletions src/Assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@

namespace Brain\Assets;

use Brain\Assets\Enqueue\Collection;
use Brain\Assets\Enqueue\JsEnqueue;
use Brain\Assets\Enqueue\Strategy;

class Assets
{
public const CSS = 'css';
Expand All @@ -26,13 +22,15 @@ class Assets
public const VIDEO = 'videos';
public const FONT = 'fonts';

private Enqueue\Collection $collection;
private UrlResolver\MinifyResolver|null $minifyResolver = null;
private string $handlePrefix;
private bool $addVersion = true;
private bool $forceSecureUrls = true;
private bool $useDepExtractionData = false;
/** @var array<string, list{string, bool}> */
private array $subFolders = [];
private bool $removalConfigured = false;

/**
* @param string $mainPluginFilePath
Expand Down Expand Up @@ -138,6 +136,15 @@ final protected function __construct(private Factory $factory)
{
// Store separately from name, so we can enable & disable as well as changing it.
$this->handlePrefix = $this->context()->name();
$this->collection = Enqueue\Collection::new($this);
}

/**
* @return Enqueue\Collection
*/
public function collection(): Enqueue\Collection
{
return clone $this->collection;
}

/**
Expand Down Expand Up @@ -542,8 +549,8 @@ public function enqueueScript(
* @param string $name
* @param string $url
* @param array $deps
* @param Strategy|bool|array|string|null $strategy
* @return JsEnqueue
* @param Enqueue\Strategy|bool|array|string|null $strategy
* @return Enqueue\JsEnqueue
*/
public function registerExternalScript(
string $name,
Expand Down Expand Up @@ -572,6 +579,42 @@ public function enqueueExternalScript(
return $this->doEnqueueOrRegisterScript('enqueue', $name, $url, $deps, $strategy);
}

/**
* @param string $name
* @return static
*/
public function dequeueStyle(string $name): static
{
return $this->deregisterOrDequeue($name, self::CSS, deregister: false);
}

/**
* @param string $name
* @return static
*/
public function deregisterStyle(string $name): static
{
return $this->deregisterOrDequeue($name, self::CSS, deregister: true);
}

/**
* @param string $name
* @return static
*/
public function dequeueScript(string $name): static
{
return $this->deregisterOrDequeue($name, self::JS, deregister: false);
}

/**
* @param string $name
* @return static
*/
public function deregisterScript(string $name): static
{
return $this->deregisterOrDequeue($name, self::JS, deregister: true);
}

/**
* @param string $name
* @return string
Expand All @@ -591,10 +634,13 @@ public function handleForName(string $name): string
/**
* @param array $jsDeps
* @param array $cssDeps
* @return Collection
* @return Enqueue\Collection
*/
public function registerAllFromManifest(array $jsDeps = [], array $cssDeps = []): Collection
{
public function registerAllFromManifest(
array $jsDeps = [],
array $cssDeps = []
): Enqueue\Collection {

$collection = [];
$urls = $this->factory->manifestUrlResolver()->resolveAll();
foreach ($urls as $name => $url) {
Expand All @@ -605,7 +651,7 @@ public function registerAllFromManifest(array $jsDeps = [], array $cssDeps = [])
$collection[] = $registered;
}

$registeredAll = Collection::new($this, ...$collection);
$registeredAll = Enqueue\Collection::new($this, ...$collection);
do_action('brain.assets.registered-all-from-manifest', $registeredAll);

return $registeredAll;
Expand All @@ -627,30 +673,40 @@ private function doEnqueueOrRegisterStyle(
string $media
): Enqueue\CssEnqueue {

$isEnqueue = $type === 'enqueue';
$handle = $this->handleForName($name);

$existing = $this->maybeRegistered($handle, $isEnqueue, self::CSS);
if ($existing instanceof Enqueue\CssEnqueue) {
return $existing;
}

[$url, $useMinify] = ($url === null)
? $this->assetUrlForEnqueue($name, self::CSS)
: [$this->adjustAbsoluteUrl($url), false];

$deps = $this->prepareDeps($deps, $url, $useMinify);

$isEnqueue = $type === 'enqueue';
/** @var callable $callback */
$callback = $isEnqueue ? 'wp_enqueue_style' : 'wp_register_style';

$callback($handle, $url, $deps, null, $media);

return $isEnqueue
$enqueued = $isEnqueue
? Enqueue\CssEnqueue::new($handle)
: Enqueue\CssEnqueue::newRegistration($handle);
$this->collection = $this->collection->append($enqueued);
$this->setupRemoval();

return $enqueued;
}

/**
* @param 'register'|'enqueue' $type
* @param string $name
* @param string|null $url
* @param array $deps
* @param Strategy|bool|array|string|null $strategy
* @param Enqueue\Strategy|bool|array|string|null $strategy
* @return Enqueue\JsEnqueue
*/
private function doEnqueueOrRegisterScript(
Expand All @@ -661,23 +717,57 @@ private function doEnqueueOrRegisterScript(
Enqueue\Strategy|bool|array|string|null $strategy
): Enqueue\JsEnqueue {

$isEnqueue = $type === 'enqueue';
$handle = $this->handleForName($name);

$existing = $this->maybeRegistered($handle, $isEnqueue, self::JS);
if ($existing instanceof Enqueue\JsEnqueue) {
return $existing;
}

[$url, $useMinify] = ($url === null)
? $this->assetUrlForEnqueue($name, self::JS)
: [$this->adjustAbsoluteUrl($url), false];

$strategy = Enqueue\Strategy::new($strategy);
$deps = $this->prepareDeps($deps, $url, $useMinify);

$isEnqueue = $type === 'enqueue';
/** @var callable $callback */
$callback = $isEnqueue ? 'wp_enqueue_script' : 'wp_register_script';

$callback($handle, $url, $deps, null, $strategy->toArray());

return $isEnqueue
$enqueued = $isEnqueue
? Enqueue\JsEnqueue::new($handle, $strategy)
: Enqueue\JsEnqueue::newRegistration($handle, $strategy);
$this->collection = $this->collection->append($enqueued);
$this->setupRemoval();

return $enqueued;
}

/**
* @param string $name
* @param 'css'|'js' $type
* @param bool $deregister
* @return static
*/
private function deregisterOrDequeue(string $name, string $type, bool $deregister): static
{
$handle = $this->handleForName($name);
$existing = $this->maybeRegistered($handle, null, $type);
if ($existing instanceof Enqueue\Enqueue) {
$deregister ? $existing->deregister() : $existing->dequeue();

return $this;
}

match ($type) {
'css' => $deregister ? wp_deregister_style($handle) : wp_dequeue_script($handle),
'js' => $deregister ? wp_deregister_script($handle) : wp_dequeue_script($handle),
};

return $this;
}

/**
Expand Down Expand Up @@ -934,4 +1024,45 @@ private function unminifiedUrl(string $url): ?string

return null;
}

/**
* @param string $handle
* @param bool|null $enqueue
* @param 'css'|'js' $type
* @return Enqueue\Enqueue|null
*/
private function maybeRegistered(string $handle, ?bool $enqueue, string $type): ?Enqueue\Enqueue
{
$existing = $this->collection()->oneByHandle($handle, $type);
if (($existing !== null) || ($enqueue === null)) {
if (($existing !== null) && ($enqueue === true) && !$existing->isEnqueued()) {
$existing->enqueue();
}

return $existing;
}

if (($type === 'css') && wp_styles()->query($handle)) {
wp_dequeue_style($handle);
wp_deregister_style($handle);
} elseif (($type === 'js') && wp_scripts()->query($handle)) {
wp_dequeue_script($handle);
wp_deregister_script($handle);
}

return null;
}

/**
* @return void
*/
private function setupRemoval(): void
{
$this->removalConfigured or $this->removalConfigured = add_action(
'brain.assets.deregistered',
function (Enqueue\Enqueue $enqueue): void {
$this->collection = $this->collection->remove($enqueue);
}
);
}
}
1 change: 1 addition & 0 deletions src/Enqueue/AbstractEnqueue.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ final public function deregister(): void
$this->isCss()
? wp_deregister_style($this->handle())
: wp_deregister_script($this->handle());
do_action('brain.assets.deregistered', $this);
}

/**
Expand Down
Loading

0 comments on commit 92e49bd

Please sign in to comment.