Skip to content

Commit

Permalink
feat(src) support callable to provide the localization data
Browse files Browse the repository at this point in the history
  • Loading branch information
lucatume committed Apr 29, 2024
1 parent 93c62e4 commit 5bd9b09
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 3 deletions.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ A library for managing asset registration and enqueuing in WordPress.
* [Conditional enqueuing](#conditional-enqueuing)
* [Firing a callback after enqueuing occurs](#firing-a-callback-after-enqueuing-occurs)
* [Output JS data](#output-js-data)
* [Using a callable to provide localization data](#using-a-callable-to-provide-localization-data)
* [Output content before/after a JS asset is output](#output-content-beforeafter-a-js-asset-is-output)
* [Style meta data](#style-meta-data)

Expand Down Expand Up @@ -500,6 +501,28 @@ Note the `my-second-script-mod` handle is overriding a specific nested
key, `boomshakalaka.project.secondScriptData.animal`, in the `boomshakalaka.project.secondScriptData` object while
preserving the other keys.

#### Using a callable to provide localization data

If you need to provide localization data dynamically, you can use a callable to do so. The callable will be called
when the asset is enqueued and the return value will be used. The callable will be passed the asset as the first
argument and should return an array.

```php
Asset::add( 'my-script', 'js/some-asset.js' )
->add_localize_script(
'boomshakalaka.project.myScriptData',
function( Asset $asset ) {
return [
'animal' => 'cat',
'color' => 'orange',
];
}
)
->register();
```

Any valid callable can be used, including Closures, like in the example above.

### Output content before/after a JS asset is output

There may be times when you wish to output markup or text immediately before or immediately after outputting the JS
Expand Down
6 changes: 4 additions & 2 deletions src/Assets/Asset.php
Original file line number Diff line number Diff line change
Expand Up @@ -414,11 +414,13 @@ public function call_after_enqueue( $callable ) {
* @since 1.0.0
*
* @param string $object_name JS object name.
* @param array $data Data assigned to the JS object.
* @param array|callable $data Data assigned to the JS object. If a callable is passed, it will be called
* when the asset is enqueued and the return value will be used. The callable
* will be passed the asset as the first argument and should return an array.
*
* @return static
*/
public function add_localize_script( string $object_name, array $data ) {
public function add_localize_script( string $object_name, $data ) {
if ( str_contains( $object_name, '.' ) ) {
$this->custom_localize_script_objects[] = [ $object_name, $data ];
} else {
Expand Down
7 changes: 6 additions & 1 deletion src/Assets/Assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ public function filter_add_localization_data( $tag, $handle ) {

// If we have a Callable as the Localize data we execute it.
if ( is_callable( $localize ) ) {
$localize = call_user_func( $localize, $asset );
$localize = $localize( $asset );
}

wp_localize_script( $asset->get_slug(), $key, $localize );
Expand All @@ -378,6 +378,11 @@ public function filter_add_localization_data( $tag, $handle ) {
* Print the dot.notation namespaced objects for the asset.
*/
foreach ( $custom_localize_scripts as [$object_name, $data] ) {
// If we have a Callable as the Localize data we execute it.
if ( is_callable( $data ) ) {
$data = $data( $asset );
}

$localized_key = "{$asset->get_slug()}::{$object_name}";

if ( in_array( $localized_key, $this->localized, true ) ) {
Expand Down
51 changes: 51 additions & 0 deletions tests/wpunit/AssetsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -215,4 +215,55 @@ public function should_allow_localizing_data_in_normal_and_namespaced_form_for_s
$apply_filters
);
}

/**
* It should allow localizing data using a Closure
*
* @test
*/
public function should_allow_localizing_data_using_a_closure(): void {
$resolved_one = false;
$resolved_two = false;
$data_callback_one = function () use ( &$resolved_one ) {
$resolved_one = true;

return [
'animal' => 'cat',
'color' => 'orange',
];
};
$data_callback_two = function () use ( &$resolved_two ) {
$resolved_two = true;

return [
'animal' => 'dog',
'color' => 'green',
];
};

Asset::add( 'my-script-with-closure-data', 'test-script.js' )
->add_localize_script( 'scriptWithClosureData', $data_callback_one )
->add_localize_script( 'acme.project.closureData', $data_callback_two )
->register();

$this->assertFalse( $resolved_one, 'The first callback should not have been resolved yet.' );
$this->assertFalse( $resolved_two, 'The second callback should not have been resolved yet.' );

$apply_filters = apply_filters( 'script_loader_tag', '', 'my-script-with-closure-data' );
$this->assertEquals( <<< SCRIPT
<script id="my-script-with-closure-data-js-extra">
var scriptWithClosureData = {"animal":"cat","color":"orange"};
</script>
<script id="my-script-with-closure-data-ns-extra">
window.acme = window.acme || {};
window.acme.project = window.acme.project || {};
window.acme.project.closureData = Object.assign(window.acme.project.closureData || {}, {"animal":"dog","color":"green"});
</script>
SCRIPT,
$apply_filters
);

$this->assertTrue( $resolved_one );
$this->assertTrue( $resolved_two );
}
}

0 comments on commit 5bd9b09

Please sign in to comment.