<?php
/**
* File containing the class Sensei_Blocks.
*
* @package sensei
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class Sensei_Blocks
*/
class Sensei_Blocks {
/**
* Course blocks.
*
* @var Sensei_Course_Blocks
*/
public $course;
/**
* Course blocks.
*
* @var Sensei_Lesson_Blocks
*/
private $lesson;
/**
* Quiz blocks.
*
* @var Sensei_Quiz_Blocks
*/
public $quiz;
/**
* Page blocks.
*
* @var Sensei_Page_Blocks
*/
public $page;
/**
* Sensei_Blocks constructor.
*/
public function __construct() {
// Skip if Gutenberg is not available.
if ( ! function_exists( 'register_block_type' ) ) {
return;
}
// Register generic blocks assets.
add_action( 'init', [ $this, 'register_generic_assets' ] );
if ( is_wp_version_compatible( '5.8' ) ) {
add_filter( 'block_categories_all', [ $this, 'sensei_block_categories' ], 10, 2 );
} else {
add_filter( 'block_categories', [ $this, 'sensei_block_categories' ], 10, 2 );
}
// Init blocks.
$this->course = new Sensei_Course_Blocks();
$this->lesson = new Sensei_Lesson_Blocks();
$this->quiz = new Sensei_Quiz_Blocks();
$this->page = new Sensei_Page_Blocks();
new Sensei_Global_Blocks();
new Sensei\Blocks\Course_Theme_Blocks();
}
/**
* Register generic assets.
*
* @access private
*/
public function register_generic_assets() {
Sensei()->assets->register( 'sensei-shared-blocks', 'blocks/shared.js', [], true );
Sensei()->assets->register( 'sensei-shared-blocks-style', 'blocks/shared-style.css' );
Sensei()->assets->register( 'sensei-shared-blocks-editor-style', 'blocks/shared-style-editor.css' );
Sensei()->assets->register( 'sensei-editor-components-style', 'blocks/editor-components/editor-components-style.css' );
Sensei()->assets->register( 'sensei-blocks-frontend', 'blocks/frontend.js', [], true );
Sensei()->assets->register( 'sensei-theme-blocks', 'css/sensei-theme-blocks.css' );
Sensei()->assets->register( 'sensei-learning-mode-compat', 'css/learning-mode-compat.css' );
if ( ! current_theme_supports( 'sensei-learning-mode' ) ) {
Sensei()->assets->register( 'sensei-learning-mode', 'css/learning-mode.css', [ 'sensei-theme-blocks', 'sensei-learning-mode-compat' ] );
} else {
Sensei()->assets->register( 'sensei-learning-mode', 'css/learning-mode.css', [ 'sensei-theme-blocks' ] );
}
Sensei()->assets->register( 'sensei-learning-mode-editor', 'css/learning-mode.editor.css', [ 'sensei-learning-mode', 'sensei-theme-blocks' ] );
wp_register_script( 'sensei-youtube-iframe-api', 'https://www.youtube.com/iframe_api', [], 'unversioned', false );
wp_register_script( 'sensei-vimeo-iframe-api', 'https://player.vimeo.com/api/player.js', [], 'unversioned', false );
wp_add_inline_script(
'sensei-youtube-iframe-api',
'window.senseiYouTubeIframeAPIReady = new Promise( ( resolve ) => {
const previousYouTubeIframeAPIReady =
window.onYouTubeIframeAPIReady !== undefined
? window.onYouTubeIframeAPIReady
: () => {};
window.onYouTubeIframeAPIReady = () => {
resolve();
previousYouTubeIframeAPIReady();
};
} )',
'before'
);
}
/**
* Add Sensei LMS block category.
*
* @access private
*
* @param array $categories Current categories.
* @param WP_Post|WP_Block_Editor_Context $context Either the WP Post (pre-WP 5.8) or the context object.
*
* @return array Filtered categories.
*/
public function sensei_block_categories( $categories, $context ) {
return array_merge(
[
[
'slug' => 'sensei-lms',
'title' => __( 'Sensei LMS', 'sensei-lms' ),
],
],
$categories
);
}
/**
* Register Sensei block. It's a wrapper for `register_block_type` or
* `register_block_type_from_metadata`, allowing to filter the args.
*
* @param string $block_name Block name.
* @param array $block_args Block arguments.
* @param string $file_or_folder Path to the JSON file with metadata definition for
* the block or path to the folder where the `block.json`
* file is located. The block will be registered using
* `register_block_type_from_metadata` if it's defined.
*/
public static function register_sensei_block( $block_name, $block_args, $file_or_folder = null ) {
if ( WP_Block_Type_Registry::get_instance()->is_registered( $block_name ) ) {
return;
}
/**
* Filter the args of the Sensei blocks.
*
* In WordPress versions 5.5 and later, block type arguments can be filtered by using register_block_type_args
* instead. This filter exists to support earlier versions only.
*
* Notice that for blocks being registered using the `$file_or_folder`, this filter runs before the
* `register_block_type_from_metadata`.
*
* @see register_block_type
* @see register_block_type_from_metadata
*
* @since 3.6.0
*
* @hook sensei_block_type_args
*
* @param {array} $block_args The block arguments as defined by register_block_type.
* @param {string} $block_name Block name.
* @return {array} Block args.
*/
$block_args = apply_filters( 'sensei_block_type_args', $block_args, $block_name );
if ( null === $file_or_folder ) {
register_block_type( $block_name, $block_args );
} else {
register_block_type_from_metadata( $file_or_folder, $block_args );
}
}
/**
* Check if the current post has any Sensei blocks.
*
* @param int|WP_Post|null $post Post.
*
* @return bool
*/
public function has_sensei_blocks( $post = null ) {
if ( ! is_string( $post ) ) {
$wp_post = get_post( $post );
if ( $wp_post instanceof WP_Post ) {
$post = $wp_post->post_content;
}
}
return false !== strpos( (string) $post, '<!-- wp:sensei-lms/' );
}
/**
* Update the URL of a button block.
*
* @param string $block_content The block content about to be appended.
* @param array $block The full block, including name and attributes.
* @param string $class_name The CSS class name used to identify the correct block.
* @param string $url The URL to navigate to when the button is clicked.
*
* @return string Block HTML.
*/
public static function update_button_block_url( $block_content, $block, $class_name, $url ): string {
if (
! isset( $block['blockName'] )
|| 'core/button' !== $block['blockName']
|| ! isset( $block['attrs']['className'] )
|| false === strpos( $block['attrs']['className'], $class_name )
) {
return $block_content;
}
if ( ! $url ) {
return $block_content;
}
$dom = new DomDocument();
$dom->loadHTML( $block_content );
$parent_node = $dom->getElementsByTagName( 'div' )->length > 0 ? $dom->getElementsByTagName( 'div' )[0] : '';
if ( ! $parent_node || ! $parent_node->hasAttributes() ) {
return $block_content;
}
// Get anchor node.
$anchor_node = $parent_node->getElementsByTagName( 'a' )->length > 0 ? $parent_node->getElementsByTagName( 'a' )[0] : '';
// Open the appropriate page when the button is clicked.
if ( $anchor_node ) {
$anchor_node->setAttribute( 'href', $url );
$block_content = $dom->saveHTML( $parent_node );
}
return $block_content;
}
}