Skip to content

Instantly share code, notes, and snippets.

@aristath
Created January 3, 2020 12:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aristath/77eda3f32ca8db17977360bcb14f1a3f to your computer and use it in GitHub Desktop.
Save aristath/77eda3f32ca8db17977360bcb14f1a3f to your computer and use it in GitHub Desktop.
<?php // phpcs:ignore WordPress.Files.FileName
/**
*
* Add blocks styles inline.
*
* @package WPTRT/BlockAssets
*/
namespace WPTRT;
/**
* Template handler.
*
* @since 1.0.0
*/
class BlockAssets {
/**
* An array of blocks used in this page.
*
* @access protected
* @since 1.0.0
* @var array
*/
protected $blocks = [];
/**
* An array of paths to include.
*
* @access protected
* @since 1.0.0
* @var array
*/
protected $paths = [];
/**
* Constructor.
*
* @since 1.0.0
* @access public
*/
public function __construct() {
$this->bootstrap();
}
/**
* Bootstraps this package.
*
* @access protected
* @since 1.0.0
* @return void
*/
protected function bootstrap() {
/**
* Remove core styles.
* We'll be adding inline just the blocks styles we need for this request in the footer.
*/
add_action( 'wp_enqueue_scripts', [ $this, 'scripts' ] );
/**
* Use a filter to figure out which blocks are used.
* We'll use this to populate the $blocks property of this object
* and enqueue the CSS needed for them.
*/
add_filter( 'render_block', [ $this, 'render_block' ], 10, 2 );
/**
* Find the paths we want to include.
* Populates the $paths property of this object.
*/
add_action( 'wp_footer', [ $this, 'populate_paths' ], 100 );
/**
* Print the styles.
* We use priority 101 because we need this to run after the $paths have been populated.
*/
add_action( 'wp_footer', [ $this, 'print_styles' ], 101 );
}
/**
* Enqueue scripts.
*
* @access public
* @since 1.0.0
*/
public function scripts() {
// Dequeue wp-core blocks styles. These will be added inline.
wp_dequeue_style( 'wp-block-library' );
wp_dequeue_style( 'wp-block-library-theme' );
}
/**
* Inline stylesheets builder.
*
* @access public
* @since 1.0.0
* @return void
*/
public function populate_paths() {
// Add blocks styles.
$blocks = $this->get_blocks();
foreach ( $blocks as $block ) {
// Remove "core/" for core blocks.
$block = str_replace( 'core/', '', $block );
// Replace "/" with "_" for non-core blocks.
$block = str_replace( '/', '_', $block );
// Locate the file path.
$path = get_theme_file_path( "assets/css/blocks/$block.min.css" );
/**
* Filter the path.
*
* @since 1.0.0
* @param string $path Absolute file path.
* @param string $block The block-name.
* @return string
*/
$path = apply_filters( 'wptrt_block_asset_loader_path', $path, $block );
if ( file_exists( $path ) ) {
$this->add_file( $path );
}
}
}
/**
* Adds a file to the object's $paths property.
*
* @access public
* @since 1.0.0
* @param string $path The path we want to add.
* @return void
*/
public function add_file( $path ) {
if ( ! in_array( $path, $this->paths, true ) ) {
$this->paths[] = $path;
}
}
/**
* Filters the content of a single block.
*
* @since 1.0.0
* @access public
* @param string $block_content The block content about to be appended.
* @param array $block The full block, including name and attributes.
* @return string Returns $block_content unaltered.
*/
public function render_block( $block_content, $block ) {
if ( $block['blockName'] ) {
$this->blocks[] = $block['blockName'];
}
return $block_content;
}
/**
* Get an array of blocks used in this page.
*
* @access public
* @since 1.0.0
* @return array
*/
public function get_blocks() {
return array_unique( $this->blocks );
}
/**
* Print styles.
*
* @access public
* @since 1.0.0
* @return void
*/
public function print_styles() {
$styles = '';
foreach ( $this->paths as $path ) {
$styles .= file_get_contents( $path );
}
echo '<style id="blocks-inline-styles>';
// Strip all tags here. No need for further escaping since this is interpreted as a style.
echo wp_strip_all_tags( $styles );
echo '</style>';
}
}
/* Omit closing PHP tag to avoid "Headers already sent" issues. */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment