Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prepare for new block variations 3/3: block variation loading #898

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
f749adb
Register & require_once block variations
carstingaxion Sep 21, 2024
cb45d04
Include variations in webpack config & copy all php classes to build
carstingaxion Sep 21, 2024
8a3ee5f
Add TEST block-variation (to illustrate the idea)
carstingaxion Sep 21, 2024
7ff1c5f
NEW Block_Variation Trait
carstingaxion Sep 21, 2024
fb0da1c
Fix error: 'copy-webpack-plugin' should be listed in the project's d…
carstingaxion Sep 25, 2024
190a84c
Fix for CS
carstingaxion Sep 25, 2024
11a1bd0
NEW hooks to assert
carstingaxion Oct 1, 2024
ee4243a
Reduce to relevant values before return
carstingaxion Oct 1, 2024
9b99841
NEW test for get_block_variations() method
carstingaxion Oct 1, 2024
e5b8ea2
NEW unittest group "blocks"
carstingaxion Oct 1, 2024
52ef721
(WIP) NEW test for register_block_variations() method
carstingaxion Oct 1, 2024
f5acaf7
NEW test to check for the existence of pattern slugs in developer docs
carstingaxion Oct 1, 2024
527b5ce
NEW test for register_block_patterns() method
carstingaxion Oct 1, 2024
76c237c
Fix for CS
carstingaxion Oct 1, 2024
f18a2c1
NEW assertion
carstingaxion Oct 1, 2024
689e6da
(failing) NEW test for register_block_variations() method
carstingaxion Oct 1, 2024
25fb97d
Autoload one singleton per block variation
carstingaxion Oct 5, 2024
0e0bd98
Remove example block-variation
carstingaxion Oct 5, 2024
85c8d42
npm uninstall copy-webpack-plugin
carstingaxion Oct 5, 2024
1506d6e
Check if folder exists before processing
carstingaxion Oct 5, 2024
76c5268
BUILD
carstingaxion Oct 5, 2024
e466a0a
Merge branch 'main' into feature/block-variation-loading
carstingaxion Oct 5, 2024
8a8b92c
Fix for CS
carstingaxion Oct 5, 2024
1c60c65
Make sure to keep this folder (to avoid errors until the first block-…
carstingaxion Oct 5, 2024
2d62c27
Fix error due to non-existing variations folder
carstingaxion Oct 5, 2024
d50c636
Fix for CS
carstingaxion Oct 5, 2024
e4a54d1
Ignore phpstan-error until first block-variation is in place.
carstingaxion Oct 5, 2024
b92e3df
Some adjustments, cleanup, fix conflicts from develop.
mauteri Oct 12, 2024
6c9727a
Push update.
mauteri Oct 12, 2024
70d8823
Reverse.
mauteri Oct 12, 2024
9d22aa0
Resolve conflicts.
mauteri Oct 12, 2024
0bf75c4
Fix conflict.
mauteri Oct 12, 2024
fd5faea
Remove "<<<<..." left-over
carstingaxion Oct 13, 2024
f6c93b2
Move asset-methods into assets-class ;)
carstingaxion Oct 16, 2024
fcc06e3
Remove static keyword
carstingaxion Oct 16, 2024
5d76429
Fix failing tests
carstingaxion Oct 16, 2024
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
140 changes: 137 additions & 3 deletions includes/core/classes/class-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore

use GatherPress\Core\Block;
use GatherPress\Core\Traits\Singleton;
use Error;

/**
* Class Assets.
Expand Down Expand Up @@ -87,6 +89,8 @@ protected function setup_hooks(): void {
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
add_action( 'enqueue_block_assets', array( $this, 'enqueue_scripts' ) );
add_action( 'enqueue_block_editor_assets', array( $this, 'editor_enqueue_scripts' ) );
add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_variation_assets' ) );
add_action( 'init', array( $this, 'register_variation_assets' ) );
add_action( 'wp_head', array( $this, 'add_global_object' ), PHP_INT_MIN );
// Set priority to 11 to not conflict with media modal.
add_action( 'admin_footer', array( $this, 'event_communication_modal' ), 11 );
Expand Down Expand Up @@ -418,14 +422,144 @@ protected function unregister_blocks(): array {
*
* @since 1.0.0
*
* @param string $asset The file name of the asset.
* @param string $asset The file name of the asset.
* @param ?string $path (Optional) The absolute path to the asset file
* or null to use the path based on the default naming scheme.
* @return array An array containing asset-related data.
*/
protected function get_asset_data( string $asset ): array {
protected function get_asset_data( string $asset, string $path = null ): array {
$path = $path ?? $this->path . sprintf( '%s.asset.php', $asset );
if ( empty( $this->asset_data[ $asset ] ) ) {
$this->asset_data[ $asset ] = require_once $this->path . sprintf( '%s.asset.php', $asset );
$this->asset_data[ $asset ] = require_once $path;
}

return (array) $this->asset_data[ $asset ];
}

/**
* Register all assets.
*
* @since 1.0.0
*
* @return void
*/
public function register_variation_assets(): void {
array_map(
array( $this, 'register_asset' ),
Block::get_instance()->get_block_variations()
);
}

/**
* Enqueue all assets.
*
* @since 1.0.0
*
* @return void
*/
public function enqueue_variation_assets(): void {
array_map(
array( $this, 'enqueue_asset' ),
Block::get_instance()->get_block_variations()
);
}

/**
* Register a new script and sets translated strings for the script.

* @since 1.0.0
*
* @param string $folder_name Slug of the block to register scripts and translations for.
* @param string $build_dir Name of the folder ro register assets from, relative to the plugins root directory.
*
* @return void
*/
protected function register_asset( string $folder_name, $build_dir = 'variations/' ): void {
$slug = sprintf( 'gatherpress-%s', $folder_name );
$folders = sprintf( '%1$s%2$s', $build_dir, $folder_name );
$dir = sprintf( '%1$s%2$s', $this->path, $folders );
$path_php = sprintf( '%1$s/index.asset.php', $dir );
$path_css = sprintf( '%1$s/index.css', $dir );
$url_js = sprintf( '%s/index.js', $this->build );
$url_css = sprintf( '%s/index.css', $this->build );

if ( ! $this->asset_exists( $path_php, $folder_name ) ) {
return;
}

$asset = $this->get_asset_data( $folder_name, $path_php );

wp_register_script(
$slug,
$url_js,
$asset['dependencies'],
$asset['version'],
true
);

wp_set_script_translations( $slug, 'gatherpress' );

if ( $this->asset_exists( $path_css, $folder_name ) ) {
wp_register_style(
$slug,
$url_css,
array( 'global-styles' ),
$asset['version'],
'screen'
);
}
}

/**
* Enqueue a script and a style with the same name, if registered.
*
* @since 1.0.0
*
* @param string $folder_name Slug of the block to load the frontend scripts for.
*
* @return void
*/
protected function enqueue_asset( string $folder_name ): void {
$slug = sprintf( 'gatherpress-%s', $folder_name );
wp_enqueue_script( $slug );

if ( wp_style_is( $slug, 'registered' ) ) {
wp_enqueue_style( $slug );
}
}

/**
* A better file_exists with built-in error handling.
*
* @since 1.0.0
*
* @throws Error Throws error for non-existent file with given path,
* if this is a development environment,
* returns false for all other environments.
*
* @param string $path Absolute path to the file to check.
* @param string $name Name of the file.
*
* @return bool
*/
protected function asset_exists( string $path, string $name ): bool {
if ( ! file_exists( $path ) ) {
$error_message = sprintf(
/* Translators: %s Name of a block-asset */
__(
'You need to run `npm start` or `npm run build` for the "%s" block-asset first.',
'gatherpress'
),
$name
);

if ( in_array( wp_get_environment_type(), array( 'local', 'development' ), true ) ) {
throw new Error( esc_html( $error_message ) );
} else {
// Should write to the \error_log( $error_message ); if possible.
return false;
}
}
return true;
}
}
1 change: 1 addition & 0 deletions includes/core/classes/class-autoloader.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ static function ( string $class_string = '' ): void {
array_unshift( $structure, 'includes' );

switch ( $class_type ) {
case 'blocks':
case 'commands':
case 'settings':
case 'traits':
Expand Down
74 changes: 74 additions & 0 deletions includes/core/classes/class-block.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ class Block {
*/
use Singleton;

/**
* An array used to cache block variation names.
*
* @since 1.0.0
* @var array
*/
protected array $block_variation_names = array();

/**
* Class constructor.
*
Expand All @@ -49,6 +57,8 @@ protected function __construct() {
* @return void
*/
protected function setup_hooks(): void {
// Priority 9 needed to allow the Block_Variation(s) to register their assets on init:10, without worries.
add_action( 'init', array( $this, 'register_block_variations' ), 9 );
add_action( 'init', array( $this, 'register_block_patterns' ) );
// Priority 11 needed for block.json translations of title and description.
add_action( 'init', array( $this, 'register_blocks' ), 11 );
Expand All @@ -74,6 +84,70 @@ public function register_blocks(): void {
}
}

/**
* Require files & instantiate block-variation classes.
*
* @return void
*/
public function register_block_variations(): void {
foreach ( $this->get_block_variations() as $block ) {
// Prepare namespaced class-name
// in the following shape: "GatherPress\Core\Blocks\Block_Variation" (example).
$name = join(
'\\',
array(
__NAMESPACE__,
'Blocks',
$this->get_classname_from_foldername( $block ),
)
);

if ( class_exists( $name ) ) {
$name::get_instance();
}
}
}

/**
* Get a list of subfolder names from the /build/variations/ directory.
*
* @since 1.0.0
*
* @return string[] List of block-variations foldernames.
*/
public function get_block_variations(): array {
$variations_directory = sprintf( '%1$s/build/variations/', GATHERPRESS_CORE_PATH );

if ( ! file_exists( $variations_directory ) ) {
return array();
}

if ( empty( $this->block_variation_names ) ) {
$this->block_variation_names = array_values(
array_diff(
scandir( $variations_directory ),
array( '..', '.' )
)
);
}
return array_filter( $this->block_variation_names );
}

/**
* Get class name from folder name.
*
* @todo maybe better in the Utility class?
*
* @param string $foldername String with name of a folder.
*
* @return string Class name that reflects the given foldername.
*/
protected static function get_classname_from_foldername( string $foldername ): string {
$foldername = basename( $foldername );

return ucwords( str_replace( '-', '_', $foldername ), '_' );
}

/**
* Register block patterns.
*
Expand Down
Loading
Loading