initial
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the accordion block.
|
||||
*
|
||||
* @package GenerateBlocks Pro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
require_once 'class-accordion.php';
|
||||
require_once 'class-accordion-item.php';
|
||||
require_once 'class-accordion-toggle.php';
|
||||
require_once 'class-accordion-toggle-icon.php';
|
||||
require_once 'class-accordion-content.php';
|
||||
|
||||
add_filter( 'block_editor_settings_all', 'generateblocks_pro_accordion_block_editor_settings', 20 );
|
||||
/**
|
||||
* Add block editor settings for the navigation block.
|
||||
*
|
||||
* @param array $settings The block editor settings.
|
||||
*/
|
||||
function generateblocks_pro_accordion_block_editor_settings( $settings ) {
|
||||
$blocks_to_reset = [
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-accordion',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-accordion-item',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-accordion-toggle',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-accordion-toggle-icon',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-accordion-content',
|
||||
];
|
||||
$css = implode( ',', $blocks_to_reset ) . ' {max-width:unset;margin:0}';
|
||||
$settings['styles'][] = [ 'css' => $css ];
|
||||
|
||||
return $settings;
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Accordion block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Accordion block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Accordion_Content extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/accordion-content';
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Accordion block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Accordion block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Accordion_Item extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/accordion-item';
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Accordion block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Accordion block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Accordion_Toggle_Icon extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/accordion-toggle-icon';
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Accordion block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Accordion block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Accordion_Toggle extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/accordion-toggle';
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
// Bail here if the HTML Tag Processor isn't available.
|
||||
if ( ! class_exists( 'WP_HTML_Tag_Processor' ) ) {
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
$open_by_default = $block->context['generateblocks/accordion/openByDefault'] ?? false;
|
||||
$processor = new WP_HTML_Tag_Processor( $block_content );
|
||||
$tag_name = $attributes['tagName'] ?? 'div';
|
||||
$main_tag = $processor->next_tag( $tag_name );
|
||||
$updated_html = false;
|
||||
|
||||
if ( $processor && $main_tag ) {
|
||||
if ( $open_by_default ) {
|
||||
$processor->add_class( 'gb-block-is-current' );
|
||||
$updated_html = true;
|
||||
}
|
||||
|
||||
if ( 'div' === $tag_name ) {
|
||||
if ( ! $processor->get_attribute( 'tabindex' ) ) {
|
||||
$processor->set_attribute( 'tabindex', '0' );
|
||||
}
|
||||
|
||||
if ( ! $processor->get_attribute( 'role' ) ) {
|
||||
$processor->set_attribute( 'role', 'button' );
|
||||
}
|
||||
|
||||
$updated_html = true;
|
||||
}
|
||||
|
||||
if ( $updated_html ) {
|
||||
$block_content = $processor->get_updated_html();
|
||||
}
|
||||
}
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Accordion block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Accordion block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Accordion extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/accordion';
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
if ( ! wp_style_is( 'generateblocks-accordion', 'enqueued' ) ) {
|
||||
self::enqueue_style();
|
||||
}
|
||||
|
||||
if ( ! wp_script_is( 'generateblocks-accordion', 'enqueued' ) ) {
|
||||
self::enqueue_assets();
|
||||
}
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue block styles.
|
||||
*/
|
||||
private static function enqueue_style() {
|
||||
wp_enqueue_style(
|
||||
'generateblocks-accordion',
|
||||
GENERATEBLOCKS_PRO_DIR_URL . 'dist/accordion-style.css',
|
||||
[],
|
||||
GENERATEBLOCKS_PRO_VERSION
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue block scripts.
|
||||
*/
|
||||
private static function enqueue_scripts() {
|
||||
wp_enqueue_script(
|
||||
'generateblocks-accordion',
|
||||
GENERATEBLOCKS_PRO_DIR_URL . 'dist/accordion.js',
|
||||
[],
|
||||
GENERATEBLOCKS_PRO_VERSION,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue block assets.
|
||||
*/
|
||||
public static function enqueue_assets() {
|
||||
self::enqueue_scripts();
|
||||
self::enqueue_style();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
<?php
|
||||
/**
|
||||
* Register our blocks.
|
||||
*
|
||||
* @package GenerateBlocks Pro
|
||||
*/
|
||||
|
||||
add_action( 'init', 'generateblocks_pro_register_blocks' );
|
||||
/**
|
||||
* Register the GenerateBlocks Pro blocks.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
function generateblocks_pro_register_blocks() {
|
||||
if ( ! class_exists( 'GenerateBlocks_Block' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
require_once 'accordion/accordion.php';
|
||||
require_once 'tabs/tabs.php';
|
||||
require_once 'classic-menu/classic-menu.php';
|
||||
require_once 'classic-menu-item/classic-menu-item.php';
|
||||
require_once 'classic-sub-menu/classic-sub-menu.php';
|
||||
require_once 'navigation/navigation.php';
|
||||
require_once 'menu-container/menu-container.php';
|
||||
require_once 'menu-toggle/menu-toggle.php';
|
||||
require_once 'site-header/site-header.php';
|
||||
require_once 'carousel/carousel.php';
|
||||
require_once 'carousel-pagination/carousel-pagination.php';
|
||||
require_once 'carousel-items/carousel-items.php';
|
||||
require_once 'carousel-item/carousel-item.php';
|
||||
require_once 'carousel-control/carousel-control.php';
|
||||
|
||||
if ( generateblocks_pro_forms_enabled() ) {
|
||||
require_once 'form/form.php';
|
||||
require_once 'form-render/form-render.php';
|
||||
require_once 'form-field/form-field.php';
|
||||
require_once 'form-field-label/form-field-label.php';
|
||||
require_once 'form-field-control/form-field-control.php';
|
||||
}
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/accordion',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Accordion::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/accordion-item',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Accordion_Item::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/accordion-toggle',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Accordion_Toggle::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/accordion-toggle-icon',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Accordion_Toggle_Icon::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/accordion-content',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Accordion_Content::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/tabs',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Tabs::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/tabs-menu',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Tabs_Menu::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/tab-menu-item',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Tab_Menu_Item::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/tab-items',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Tab_Items::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/tab-item',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Tab_Item::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/classic-menu',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Classic_Menu::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/classic-menu-item',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Classic_Menu_Item::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/classic-sub-menu',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Classic_Sub_Menu::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/navigation',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Navigation::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/menu-toggle',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Menu_Toggle::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/menu-container',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Menu_Container::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/site-header',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Site_Header::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/carousel',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Carousel::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/carousel-pagination',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Carousel_Pagination::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/carousel-items',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Carousel_Items::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/carousel-item',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Carousel_Item::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/carousel-control',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Carousel_Control::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
if ( generateblocks_pro_forms_enabled() ) {
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/form',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Form::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/form-field',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Form_Field::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/form-field-label',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Form_Field_Label::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/form-field-control',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Form_Field_Control::render_block',
|
||||
]
|
||||
);
|
||||
|
||||
register_block_type_from_metadata(
|
||||
GENERATEBLOCKS_PRO_DIR . '/dist/blocks/form-render',
|
||||
[
|
||||
'render_callback' => 'GenerateBlocks_Block_Form_Render::render_block',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
/**
|
||||
* Registers the Carousel Control block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
// Load the class file.
|
||||
require_once GENERATEBLOCKS_PRO_DIR . 'includes/blocks/carousel-control/class-carousel-control.php';
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Carousel Control block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Carousel Control block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Carousel_Control extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/carousel-control';
|
||||
|
||||
/**
|
||||
* Render the Carousel Control block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
// Add default ARIA labels if not present using WP HTML Tag Processor
|
||||
// Only available in WordPress 6.2+, skip for older versions.
|
||||
if ( class_exists( 'WP_HTML_Tag_Processor' ) ) {
|
||||
$control_type = $attributes['controlType'] ?? 'next';
|
||||
$has_aria_label = isset( $attributes['htmlAttributes']['aria-label'] ) && ! empty( $attributes['htmlAttributes']['aria-label'] );
|
||||
|
||||
$processor = new \WP_HTML_Tag_Processor( $block_content );
|
||||
|
||||
// Find the first tag (the button/control element).
|
||||
if ( $processor->next_tag() ) {
|
||||
// Add default ARIA label if not present.
|
||||
if ( ! $has_aria_label && ! $processor->get_attribute( 'aria-label' ) ) {
|
||||
// Map control types to default ARIA labels.
|
||||
$default_labels = [
|
||||
'next' => __( 'Next slide', 'generateblocks-pro' ),
|
||||
'previous' => __( 'Previous slide', 'generateblocks-pro' ),
|
||||
'play' => __( 'Play carousel', 'generateblocks-pro' ),
|
||||
'pause' => __( 'Pause carousel', 'generateblocks-pro' ),
|
||||
'play-pause' => __( 'Toggle carousel playback', 'generateblocks-pro' ),
|
||||
'first' => __( 'Go to first slide', 'generateblocks-pro' ),
|
||||
'last' => __( 'Go to last slide', 'generateblocks-pro' ),
|
||||
];
|
||||
|
||||
$aria_label = $default_labels[ $control_type ] ?? __( 'Carousel control', 'generateblocks-pro' );
|
||||
$processor->set_attribute( 'aria-label', $aria_label );
|
||||
}
|
||||
|
||||
// For play-pause controls, ensure aria-pressed attribute exists.
|
||||
if ( 'play-pause' === $control_type && ! $processor->get_attribute( 'aria-pressed' ) ) {
|
||||
$processor->set_attribute( 'aria-pressed', 'false' );
|
||||
}
|
||||
|
||||
$block_content = $processor->get_updated_html();
|
||||
}
|
||||
}
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the carousel item block.
|
||||
*
|
||||
* @package GenerateBlocks Pro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
require_once 'class-carousel-item.php';
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Carousel Item block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Carousel Item block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Carousel_Item extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/carousel-item';
|
||||
|
||||
/**
|
||||
* Render the Carousel Item block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
/**
|
||||
* Handle the carousel block.
|
||||
*
|
||||
* @package GenerateBlocks Pro
|
||||
*/
|
||||
|
||||
// Include our files.
|
||||
require_once 'class-carousel-items.php';
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Carousel block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Carousel block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Carousel_Items extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/carousel-items';
|
||||
|
||||
/**
|
||||
* Render the Carousel block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
/**
|
||||
* Handle the carousel pagination block.
|
||||
*
|
||||
* @package GenerateBlocks Pro
|
||||
*/
|
||||
|
||||
// Include our files.
|
||||
require_once 'class-carousel-pagination.php';
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Carousel Pagination block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Carousel Pagination block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Carousel_Pagination extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/carousel-pagination';
|
||||
|
||||
/**
|
||||
* Render the Carousel Pagination block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
$to_replace = '<span class="gb-carousel-pagination-content"></span>';
|
||||
$pagination_type = $block->context['generateblocks/carousel/htmlAttributes']['data-pagination-type'] ?? 'bullets';
|
||||
$replacement = '';
|
||||
|
||||
if ( 'fraction' === $pagination_type ) {
|
||||
$replacement = '<span class="gb-carousel-current">1</span> / <span class="gb-carousel-total">1</span>';
|
||||
}
|
||||
|
||||
if ( 'bullets' === $pagination_type ) {
|
||||
$replacement = '<span class="gb-carousel-dot" style="display: inline-block !important;"></span>';
|
||||
}
|
||||
|
||||
if ( $replacement ) {
|
||||
$block_content = str_replace( $to_replace, $replacement, $block_content );
|
||||
}
|
||||
|
||||
// Add default ARIA attributes if not present using WP HTML Tag Processor
|
||||
// Only available in WordPress 6.2+, skip for older versions.
|
||||
if ( class_exists( 'WP_HTML_Tag_Processor' ) ) {
|
||||
$has_aria_label = isset( $attributes['htmlAttributes']['aria-label'] ) && ! empty( $attributes['htmlAttributes']['aria-label'] );
|
||||
|
||||
$processor = new \WP_HTML_Tag_Processor( $block_content );
|
||||
|
||||
// Find the first tag (the pagination container).
|
||||
if ( $processor->next_tag() ) {
|
||||
// Add default ARIA label if not present.
|
||||
if ( ! $has_aria_label && ! $processor->get_attribute( 'aria-label' ) ) {
|
||||
// Map pagination types to default ARIA labels.
|
||||
$default_labels = [
|
||||
'bullets' => __( 'Carousel pagination', 'generateblocks-pro' ),
|
||||
'fraction' => __( 'Carousel slide counter', 'generateblocks-pro' ),
|
||||
'progressbar' => __( 'Carousel progress', 'generateblocks-pro' ),
|
||||
];
|
||||
|
||||
$aria_label = $default_labels[ $pagination_type ] ?? __( 'Carousel pagination', 'generateblocks-pro' );
|
||||
$processor->set_attribute( 'aria-label', $aria_label );
|
||||
}
|
||||
|
||||
// Add role attribute for bullets pagination if not present.
|
||||
if ( 'bullets' === $pagination_type && ! $processor->get_attribute( 'role' ) ) {
|
||||
$processor->set_attribute( 'role', 'navigation' );
|
||||
}
|
||||
|
||||
$block_content = $processor->get_updated_html();
|
||||
}
|
||||
}
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
/**
|
||||
* Handle the carousel block.
|
||||
*
|
||||
* @package GenerateBlocks Pro
|
||||
*/
|
||||
|
||||
// Include our files.
|
||||
require_once 'class-carousel.php';
|
||||
|
||||
add_filter( 'block_editor_settings_all', 'generateblocks_pro_carousel_block_editor_settings', 20 );
|
||||
/**
|
||||
* Add block editor settings for the carousel block.
|
||||
*
|
||||
* @param array $settings The block editor settings.
|
||||
*/
|
||||
function generateblocks_pro_carousel_block_editor_settings( $settings ) {
|
||||
$blocks_to_reset = [
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-carousel',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-carousel-pagination',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-carousel-items',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-carousel-item',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-carousel-control',
|
||||
];
|
||||
$css = implode( ',', $blocks_to_reset ) . ' {max-width:unset;margin:0}';
|
||||
$settings['styles'][] = [ 'css' => $css ];
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
add_filter( 'generateblocks_block_css', 'generateblocks_pro_carousel_block_css', 10, 2 );
|
||||
/**
|
||||
* Add block CSS for the carousel block.
|
||||
*
|
||||
* @param string $css The CSS to add.
|
||||
* @param array $block The block data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function generateblocks_pro_carousel_block_css( $css, $block ) {
|
||||
if ( ! isset( $block['attributes']['uniqueId'] ) ) {
|
||||
return $css;
|
||||
}
|
||||
|
||||
$block_name = $block['block_name'] ?? '';
|
||||
|
||||
if ( 'generateblocks-pro/carousel' !== $block_name ) {
|
||||
return $css;
|
||||
}
|
||||
|
||||
$selector = '.gb-carousel-' . $block['attributes']['uniqueId'];
|
||||
$init_at_raw = $block['attributes']['htmlAttributes']['data-init-at'] ?? '';
|
||||
$init_at = '';
|
||||
|
||||
if ( is_string( $init_at_raw ) ) {
|
||||
$init_at_raw = trim( $init_at_raw );
|
||||
|
||||
if ( '' !== $init_at_raw && false === strpbrk( $init_at_raw, '{};()/*' ) ) {
|
||||
$init_at = $init_at_raw;
|
||||
|
||||
if ( is_numeric( $init_at ) ) {
|
||||
$init_at .= 'px';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $init_at ) {
|
||||
$css_rules = [
|
||||
$selector . ':not([data-gb-carousel-initialized="true"]):not([data-gb-carousel-pending="true"]) .gb-carousel-items' => [
|
||||
'position' => 'relative',
|
||||
'width' => '100%',
|
||||
'height' => '100%',
|
||||
'z-index' => '1',
|
||||
'display' => 'flex',
|
||||
'overflow-x' => 'hidden',
|
||||
'gap' => 'var(--gb-carousel-slide-gap, 0)',
|
||||
],
|
||||
$selector . ':not([data-gb-carousel-initialized="true"]) .gb-carousel-items > .gb-carousel-item' => [
|
||||
'flex' => '0 0 calc((100% - var(--gb-carousel-slide-gap, 0px) * (var(--gb-carousel-slides-per-view, 1) - 1)) / var(--gb-carousel-slides-per-view, 1))',
|
||||
'width' => '100%',
|
||||
'height' => '100%',
|
||||
'position' => 'relative',
|
||||
'transition-property' => 'transform',
|
||||
'display' => 'block',
|
||||
'user-select' => 'none',
|
||||
],
|
||||
];
|
||||
$media_query_css = generateblocks_pro_build_css_from_array( $css_rules );
|
||||
$css .= "@media (max-width: {$init_at}) {{$media_query_css}}";
|
||||
|
||||
$not_at_rule_css_rules = [
|
||||
$selector . ':not([data-gb-carousel-initialized="true"]) .gb-carousel-control' => [
|
||||
'display' => 'none',
|
||||
],
|
||||
$selector . ':not([data-gb-carousel-initialized="true"]) .gb-carousel-pagination' => [
|
||||
'display' => 'none',
|
||||
],
|
||||
];
|
||||
|
||||
$not_at_rule_css = generateblocks_pro_build_css_from_array( $not_at_rule_css_rules );
|
||||
$css .= "@media (width > {$init_at}) {{$not_at_rule_css}}";
|
||||
}
|
||||
|
||||
$grid_rows = $block['attributes']['htmlAttributes']['data-grid-rows'] ?? '';
|
||||
|
||||
if ( $grid_rows ) {
|
||||
$slides_per_view = $block['attributes']['htmlAttributes']['data-slides-per-view'] ?? '1';
|
||||
$total_items = $grid_rows * $slides_per_view;
|
||||
$selected_items = $total_items + 1;
|
||||
|
||||
$css_rules = [
|
||||
$selector . ':not([data-gb-carousel-initialized="true"]):not([data-gb-carousel-pending="true"]) > .gb-carousel-items > .gb-carousel-item:nth-child(n+' . $selected_items . ')' => [
|
||||
'display' => 'none',
|
||||
],
|
||||
];
|
||||
|
||||
$built_css = generateblocks_pro_build_css_from_array( $css_rules );
|
||||
|
||||
if ( $init_at ) {
|
||||
$css .= "@media (max-width: {$init_at}) {{$built_css}}";
|
||||
} else {
|
||||
$css .= $built_css;
|
||||
}
|
||||
}
|
||||
|
||||
return $css;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Carousel block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Carousel block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Carousel extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/carousel';
|
||||
|
||||
/**
|
||||
* Render the Carousel block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Enqueue frontend scripts and styles.
|
||||
self::enqueue_scripts();
|
||||
self::enqueue_styles();
|
||||
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue frontend scripts for the carousel.
|
||||
*/
|
||||
private static function enqueue_scripts() {
|
||||
wp_enqueue_script(
|
||||
'generateblocks-carousel',
|
||||
GENERATEBLOCKS_PRO_DIR_URL . 'dist/carousel.js',
|
||||
[],
|
||||
GENERATEBLOCKS_PRO_VERSION,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue frontend styles for the carousel.
|
||||
*/
|
||||
private static function enqueue_styles() {
|
||||
wp_enqueue_style(
|
||||
'generateblocks-carousel',
|
||||
GENERATEBLOCKS_PRO_DIR_URL . 'dist/carousel-style.css',
|
||||
[],
|
||||
GENERATEBLOCKS_PRO_VERSION
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue block assets.
|
||||
*/
|
||||
public static function enqueue_assets() {
|
||||
self::enqueue_scripts();
|
||||
self::enqueue_styles();
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Content block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Content block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Classic_Menu_Item extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/classic-menu-item';
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
/**
|
||||
* Handle the menu block.
|
||||
*
|
||||
* @package GenerateBlocks Pro
|
||||
*/
|
||||
|
||||
// Include our files.
|
||||
require_once 'class-classic-menu-item.php';
|
||||
+344
@@ -0,0 +1,344 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Content block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Content block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Classic_Menu extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/classic-menu';
|
||||
|
||||
/**
|
||||
* Cache for mega menu display checks.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $mega_menu_cache = [];
|
||||
|
||||
/**
|
||||
* Check if a mega menu overlay should display based on conditions.
|
||||
*
|
||||
* @param int $overlay_id The overlay post ID.
|
||||
* @return bool Whether the overlay should display.
|
||||
*/
|
||||
private static function should_display_mega_menu( $overlay_id ) {
|
||||
// Return false if overlays are disabled.
|
||||
if ( ! generateblocks_pro_overlays_enabled() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! $overlay_id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check cache first.
|
||||
if ( isset( self::$mega_menu_cache[ $overlay_id ] ) ) {
|
||||
return self::$mega_menu_cache[ $overlay_id ];
|
||||
}
|
||||
|
||||
// Check if post exists and is published.
|
||||
$overlay_post = get_post( $overlay_id );
|
||||
if ( ! $overlay_post || 'publish' !== $overlay_post->post_status ) {
|
||||
self::$mega_menu_cache[ $overlay_id ] = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
$overlay_post_content = do_blocks( $overlay_post->post_content ) ?? '';
|
||||
|
||||
if ( empty( $overlay_post_content ) ) {
|
||||
self::$mega_menu_cache[ $overlay_id ] = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check display conditions.
|
||||
$display_condition = get_post_meta( $overlay_id, '_gb_overlay_display_condition', true );
|
||||
$display_conditions = [];
|
||||
|
||||
if ( $display_condition ) {
|
||||
// Check if the condition post exists and is published.
|
||||
$condition_post = get_post( $display_condition );
|
||||
|
||||
if ( $condition_post && 'publish' === $condition_post->post_status ) {
|
||||
$display_conditions = get_post_meta( $display_condition, '_gb_conditions', true ) ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
$show = true;
|
||||
|
||||
if ( ! empty( $display_conditions ) ) {
|
||||
$show = GenerateBlocks_Pro_Conditions::show( $display_conditions );
|
||||
$invert_condition = GenerateBlocks_Pro_Overlays::get_overlay_meta( $overlay_id, '_gb_overlay_display_condition_invert' );
|
||||
|
||||
// If invert is enabled, flip the result.
|
||||
if ( $invert_condition ) {
|
||||
$show = ! $show;
|
||||
}
|
||||
}
|
||||
|
||||
// Cache the result.
|
||||
self::$mega_menu_cache[ $overlay_id ] = $show;
|
||||
|
||||
return $show;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Clear mega menu cache for fresh checks.
|
||||
self::$mega_menu_cache = [];
|
||||
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
$selected_menu = $attributes['menu'] ?? '';
|
||||
$unique_id = $attributes['uniqueId'] ?? '';
|
||||
|
||||
if ( ! $selected_menu || ! $unique_id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isset( $block->context['generateblocks-pro/subMenuType'] ) ) {
|
||||
$sub_menu_type = $block->context['generateblocks-pro/subMenuType'];
|
||||
} elseif ( isset( $_GET['subMenuType'] ) ) { // phpcs:ignore -- No processing of data.
|
||||
$sub_menu_type = esc_attr( $_GET['subMenuType'] ); // phpcs:ignore -- No processing of data.
|
||||
} else {
|
||||
$sub_menu_type = 'hover';
|
||||
}
|
||||
|
||||
$classes = [
|
||||
'gb-menu',
|
||||
'gb-menu--base',
|
||||
'gb-menu-' . $unique_id,
|
||||
'gb-menu--' . $sub_menu_type,
|
||||
];
|
||||
|
||||
if ( ! empty( $attributes['globalClasses'] ) ) {
|
||||
$classes = array_merge( $classes, $attributes['globalClasses'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $attributes['className'] ) ) {
|
||||
$classes[] = $attributes['className'];
|
||||
}
|
||||
|
||||
$class = implode( ' ', $classes );
|
||||
|
||||
$add_menu_item_classes = function( $classes, $menu_item ) use ( $sub_menu_type, $unique_id ) {
|
||||
$mega_menu = get_post_meta( $menu_item->ID, '_gb_mega_menu', true );
|
||||
|
||||
if ( $mega_menu && self::should_display_mega_menu( $mega_menu ) ) {
|
||||
$classes[] = 'menu-item-has-gb-mega-menu';
|
||||
$classes[] = 'menu-item-has-children';
|
||||
}
|
||||
|
||||
$classes[] = 'gb-menu-item';
|
||||
$new_unique_id = substr_replace( $unique_id, 'mi', 0, 2 );
|
||||
$classes[] = 'gb-menu-item-' . $new_unique_id;
|
||||
|
||||
// Escape classes.
|
||||
$classes = array_map( 'esc_attr', $classes );
|
||||
|
||||
return $classes;
|
||||
};
|
||||
|
||||
$add_dropdown_icon = function( $title, $menu_item ) use ( $sub_menu_type ) {
|
||||
$mega_menu = get_post_meta( $menu_item->ID, '_gb_mega_menu', true );
|
||||
$has_children = in_array( 'menu-item-has-children', $menu_item->classes, true );
|
||||
$show_mega_menu = $mega_menu && self::should_display_mega_menu( $mega_menu );
|
||||
|
||||
if ( $show_mega_menu || $has_children ) {
|
||||
$modal_id = $show_mega_menu ? 'gb-overlay-' . $mega_menu : '';
|
||||
$arrow_icon = '<svg class="gb-submenu-toggle-icon" viewBox="0 0 330 512" aria-hidden="true" width="1em" height="1em" fill="currentColor"><path d="M305.913 197.085c0 2.266-1.133 4.815-2.833 6.514L171.087 335.593c-1.7 1.7-4.249 2.832-6.515 2.832s-4.815-1.133-6.515-2.832L26.064 203.599c-1.7-1.7-2.832-4.248-2.832-6.514s1.132-4.816 2.832-6.515l14.162-14.163c1.7-1.699 3.966-2.832 6.515-2.832 2.266 0 4.815 1.133 6.515 2.832l111.316 111.317 111.316-111.317c1.7-1.699 4.249-2.832 6.515-2.832s4.815 1.133 6.515 2.832l14.162 14.163c1.7 1.7 2.833 4.249 2.833 6.515z"></path></svg>';
|
||||
|
||||
$submenu_button = sprintf(
|
||||
'<span class="gb-submenu-toggle" aria-label="%3$s" role="button" aria-expanded="false" aria-haspopup="menu" tabindex="0"%2$s>%1$s</span>',
|
||||
$arrow_icon,
|
||||
$modal_id ? ' data-gb-overlay="' . esc_attr( $modal_id ) . '" data-gb-overlay-trigger-type="click" aria-controls="' . esc_attr( $modal_id ) . '"' : '',
|
||||
sprintf(
|
||||
/* translators: %s: Menu item title. */
|
||||
esc_attr__( '%s Sub-Menu', 'generateblocks-pro' ),
|
||||
esc_attr( wp_strip_all_tags( $title ) )
|
||||
)
|
||||
);
|
||||
|
||||
if ( 'click' === $sub_menu_type ) {
|
||||
return $title . $arrow_icon;
|
||||
}
|
||||
|
||||
return $title . $submenu_button;
|
||||
}
|
||||
|
||||
return $title;
|
||||
};
|
||||
|
||||
$add_link_atts = function ( $atts, $menu_item ) use ( $sub_menu_type ) {
|
||||
$class = $atts['class'] ?? '';
|
||||
$class .= ' gb-menu-link';
|
||||
$class = trim( $class );
|
||||
$atts['class'] = esc_attr( $class );
|
||||
$disable_links = isset( $_GET['disableLinks'] ); // phpcs:ignore -- No processing of data.
|
||||
|
||||
if ( $disable_links ) {
|
||||
$atts['onClick'] = 'event.preventDefault();';
|
||||
}
|
||||
|
||||
if ( 'hover' === $sub_menu_type || 'click' === $sub_menu_type ) {
|
||||
$mega_menu = get_post_meta( $menu_item->ID, '_gb_mega_menu', true );
|
||||
$show_mega_menu = $mega_menu && self::should_display_mega_menu( $mega_menu );
|
||||
|
||||
if ( $show_mega_menu ) {
|
||||
$modal_id = 'gb-overlay-' . $mega_menu;
|
||||
|
||||
// Add directive and modal element target.
|
||||
$atts['data-gb-overlay'] = $modal_id;
|
||||
|
||||
if ( 'hover' === $sub_menu_type ) {
|
||||
$atts['data-gb-overlay-trigger-type'] = 'hover';
|
||||
}
|
||||
|
||||
$atts['aria-controls'] = $modal_id;
|
||||
}
|
||||
|
||||
if ( $show_mega_menu || in_array( 'menu-item-has-children', $menu_item->classes, true ) ) {
|
||||
if ( 'click' === $sub_menu_type ) {
|
||||
$atts['role'] = 'button';
|
||||
$atts['aria-expanded'] = 'false';
|
||||
$atts['aria-label'] = sprintf(
|
||||
/* translators: %s: Menu item title. */
|
||||
esc_attr__( '%s Sub-Menu', 'generateblocks-pro' ),
|
||||
esc_attr( wp_strip_all_tags( $menu_item->title ?? '' ) )
|
||||
);
|
||||
}
|
||||
|
||||
$atts['aria-haspopup'] = 'menu';
|
||||
}
|
||||
}
|
||||
|
||||
return $atts;
|
||||
};
|
||||
|
||||
$add_sub_menu_attributes = function( $atts, $args ) use ( $unique_id ) {
|
||||
$new_unique_id = substr_replace( $unique_id, 'sm', 0, 2 );
|
||||
$atts['class'] = 'sub-menu gb-sub-menu gb-sub-menu-' . $new_unique_id;
|
||||
|
||||
return $atts;
|
||||
};
|
||||
|
||||
$add_mega_menu = function( $item_output, $item ) {
|
||||
$item_id = $item->ID;
|
||||
$mega_menu = get_post_meta( $item_id, '_gb_mega_menu', true );
|
||||
|
||||
if ( ! $mega_menu || ! self::should_display_mega_menu( $mega_menu ) ) {
|
||||
return $item_output;
|
||||
}
|
||||
|
||||
$action_id = 'gb-mega-menu-' . $mega_menu;
|
||||
ob_start();
|
||||
do_action( $action_id, $item );
|
||||
$mega_menu_content = ob_get_clean();
|
||||
return $item_output . $mega_menu_content;
|
||||
};
|
||||
|
||||
add_filter( 'nav_menu_css_class', $add_menu_item_classes, 10, 2 );
|
||||
add_filter( 'nav_menu_submenu_attributes', $add_sub_menu_attributes, 10, 2 );
|
||||
add_filter( 'nav_menu_item_title', $add_dropdown_icon, 10, 2 );
|
||||
add_filter( 'nav_menu_link_attributes', $add_link_atts, 10, 2 );
|
||||
add_filter( 'walker_nav_menu_start_el', $add_mega_menu, 10, 2 );
|
||||
|
||||
ob_start();
|
||||
|
||||
wp_nav_menu(
|
||||
[
|
||||
'menu' => $selected_menu,
|
||||
'container' => '',
|
||||
'container_class' => '',
|
||||
'menu_class' => $class,
|
||||
'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
|
||||
'fallback_cb' => false,
|
||||
]
|
||||
);
|
||||
|
||||
remove_filter( 'nav_menu_css_class', $add_menu_item_classes, 10, 2 );
|
||||
remove_filter( 'nav_menu_submenu_attributes', $add_sub_menu_attributes, 10, 2 );
|
||||
remove_filter( 'nav_menu_item_title', $add_dropdown_icon, 10, 2 );
|
||||
remove_filter( 'nav_menu_link_attributes', $add_link_atts, 10, 2 );
|
||||
remove_filter( 'walker_nav_menu_start_el', $add_mega_menu, 10, 2 );
|
||||
|
||||
do_action( 'generateblocks_pro_after_menu_block', $attributes, is_admin() );
|
||||
|
||||
$block_content .= ob_get_clean();
|
||||
|
||||
if ( ! wp_style_is( 'generateblocks-classic-menu', 'enqueued' ) ) {
|
||||
self::enqueue_style();
|
||||
}
|
||||
|
||||
if ( ! wp_script_is( 'generateblocks-classic-menu', 'enqueued' ) ) {
|
||||
self::enqueue_scripts();
|
||||
}
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue block styles.
|
||||
*/
|
||||
private static function enqueue_style() {
|
||||
wp_enqueue_style(
|
||||
'generateblocks-classic-menu',
|
||||
GENERATEBLOCKS_PRO_DIR_URL . 'dist/classic-menu-style.css',
|
||||
[],
|
||||
GENERATEBLOCKS_PRO_VERSION
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue block scripts.
|
||||
*/
|
||||
private static function enqueue_scripts() {
|
||||
wp_enqueue_script(
|
||||
'generateblocks-classic-menu',
|
||||
GENERATEBLOCKS_PRO_DIR_URL . 'dist/classic-menu.js',
|
||||
[],
|
||||
GENERATEBLOCKS_PRO_VERSION,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue block assets.
|
||||
*/
|
||||
public static function enqueue_assets() {
|
||||
self::enqueue_scripts();
|
||||
self::enqueue_style();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/**
|
||||
* Handle the menu block.
|
||||
*
|
||||
* @package GenerateBlocks Pro
|
||||
*/
|
||||
|
||||
// Include our files.
|
||||
require_once 'class-classic-menu.php';
|
||||
|
||||
add_filter( 'block_editor_settings_all', 'generateblocks_pro_classic_menu_block_settings' );
|
||||
/**
|
||||
* Add menu block settings.
|
||||
* We need to add CSS this way as it prepends `.editor-styles-wrapper` to the selectors.
|
||||
* Including the stylesheet via block.json does not, which causes specificity issues.
|
||||
*
|
||||
* @param array $settings Block editor settings.
|
||||
* @return array
|
||||
*/
|
||||
function generateblocks_pro_classic_menu_block_settings( $settings ) {
|
||||
$navigation_css = file_get_contents( GENERATEBLOCKS_PRO_DIR . 'dist/classic-menu-style.css' ); // phpcs:ignore -- correct function to use.
|
||||
|
||||
if ( ! $navigation_css ) {
|
||||
return $settings;
|
||||
}
|
||||
|
||||
$settings['styles'][] = [
|
||||
'css' => $navigation_css,
|
||||
'source' => 'generateblocks-pro/class-menu-style',
|
||||
];
|
||||
|
||||
return $settings;
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Content block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Content block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Classic_Sub_Menu extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/classic-sub-menu';
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
/**
|
||||
* Handle the menu block.
|
||||
*
|
||||
* @package GenerateBlocks Pro
|
||||
*/
|
||||
|
||||
// Include our files.
|
||||
require_once 'class-classic-sub-menu.php';
|
||||
+627
@@ -0,0 +1,627 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Form Field Control block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form field control block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Form_Field_Control extends GenerateBlocks_Block {
|
||||
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Block name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/form-field-control';
|
||||
|
||||
/**
|
||||
* Maximum textarea rows accepted from block attributes.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
const MAX_TEXTAREA_ROWS = 100;
|
||||
|
||||
/**
|
||||
* Default allow-list for custom form control HTML attributes.
|
||||
*
|
||||
* Prefix entries ending in `-*` match all attributes with that prefix.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $allowed_html_attributes = [
|
||||
'aria-*',
|
||||
'data-*',
|
||||
'autocapitalize',
|
||||
'autocomplete',
|
||||
'enterkeyhint',
|
||||
'inputmode',
|
||||
'max',
|
||||
'maxlength',
|
||||
'min',
|
||||
'minlength',
|
||||
'pattern',
|
||||
'spellcheck',
|
||||
'step',
|
||||
'title',
|
||||
];
|
||||
|
||||
/**
|
||||
* Attributes generated by the renderer or controlled by runtime behavior.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $reserved_html_attributes = [
|
||||
'aria-invalid',
|
||||
'aria-required',
|
||||
'checked',
|
||||
'class',
|
||||
'disabled',
|
||||
'id',
|
||||
'multiple',
|
||||
'name',
|
||||
'placeholder',
|
||||
'readonly',
|
||||
'required',
|
||||
'rows',
|
||||
'selected',
|
||||
'style',
|
||||
'type',
|
||||
'value',
|
||||
];
|
||||
|
||||
/**
|
||||
* Field types where custom HTML attributes apply to one rendered control.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $custom_html_attribute_field_types = [
|
||||
'text',
|
||||
'email',
|
||||
'url',
|
||||
'tel',
|
||||
'number',
|
||||
'textarea',
|
||||
'select',
|
||||
'checkbox',
|
||||
];
|
||||
|
||||
/**
|
||||
* Field-type support for known default attributes.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $html_attribute_field_type_support = [
|
||||
'autocapitalize' => [ 'text', 'email', 'url', 'tel', 'textarea' ],
|
||||
'enterkeyhint' => [ 'text', 'email', 'url', 'tel', 'number', 'textarea' ],
|
||||
'inputmode' => [ 'text', 'email', 'url', 'tel', 'number', 'textarea' ],
|
||||
'max' => [ 'number' ],
|
||||
'maxlength' => [ 'text', 'email', 'url', 'tel', 'textarea' ],
|
||||
'min' => [ 'number' ],
|
||||
'minlength' => [ 'text', 'email', 'url', 'tel', 'textarea' ],
|
||||
'pattern' => [ 'text', 'email', 'url', 'tel', 'number' ],
|
||||
'spellcheck' => [ 'text', 'email', 'url', 'tel', 'textarea' ],
|
||||
'step' => [ 'number' ],
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the allowed custom form control HTML attributes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_allowed_html_attribute_names() {
|
||||
/**
|
||||
* Filter custom HTML attributes allowed on generated form controls.
|
||||
*
|
||||
* Prefix entries ending in `-*` match all attributes with that prefix.
|
||||
* The renderer still blocks generated/runtime attributes such as
|
||||
* `name`, `id`, `type`, `value`, `required`, `aria-required`,
|
||||
* `aria-invalid`, `style`, event handlers, `form*`, and `data-gb-*`.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @param array $allowed_attributes Allowed attribute names and prefix markers.
|
||||
*/
|
||||
$allowed_attributes = apply_filters(
|
||||
'generateblocks_form_control_html_attributes',
|
||||
self::$allowed_html_attributes
|
||||
);
|
||||
|
||||
if ( ! is_array( $allowed_attributes ) ) {
|
||||
return self::$allowed_html_attributes;
|
||||
}
|
||||
|
||||
$normalized = [];
|
||||
|
||||
foreach ( $allowed_attributes as $attribute_name ) {
|
||||
$attribute_name = self::normalize_html_attribute_name( $attribute_name, true );
|
||||
|
||||
if ( '' !== $attribute_name ) {
|
||||
$normalized[] = $attribute_name;
|
||||
}
|
||||
}
|
||||
|
||||
return array_values( array_unique( $normalized ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize custom HTML attributes before rendering generated controls.
|
||||
*
|
||||
* @param mixed $html_attributes Raw htmlAttributes block attribute.
|
||||
* @param string $field_type Normalized field type.
|
||||
* @return array
|
||||
*/
|
||||
public static function sanitize_html_attributes( $html_attributes, $field_type = '' ) {
|
||||
$field_type = is_string( $field_type ) ? $field_type : '';
|
||||
|
||||
if (
|
||||
! is_array( $html_attributes ) ||
|
||||
! in_array( $field_type, self::$custom_html_attribute_field_types, true )
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$sanitized = [];
|
||||
$allowed_attributes = self::get_allowed_html_attribute_names();
|
||||
|
||||
foreach ( $html_attributes as $attribute_name => $attribute_value ) {
|
||||
$attribute_name = self::normalize_html_attribute_name( $attribute_name );
|
||||
|
||||
if ( ! self::is_allowed_html_attribute( $attribute_name, $field_type, $allowed_attributes ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( is_array( $attribute_value ) || is_object( $attribute_value ) || null === $attribute_value ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$attribute_value = (string) $attribute_value;
|
||||
|
||||
if ( '' === $attribute_value && 0 !== strpos( $attribute_name, 'data-' ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sanitized[ $attribute_name ] = $attribute_value;
|
||||
}
|
||||
|
||||
return $sanitized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize an HTML attribute name for allow-list checks.
|
||||
*
|
||||
* @param mixed $attribute_name Raw attribute name.
|
||||
* @param bool $allow_prefix Whether `aria-*` style prefix markers are valid.
|
||||
* @return string
|
||||
*/
|
||||
private static function normalize_html_attribute_name( $attribute_name, $allow_prefix = false ) {
|
||||
if ( ! is_scalar( $attribute_name ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$attribute_name = strtolower( trim( (string) $attribute_name ) );
|
||||
$is_prefix = $allow_prefix && '-*' === substr( $attribute_name, -2 );
|
||||
$attribute_name = preg_replace( '/[^a-z0-9._:-]/', '', $attribute_name );
|
||||
|
||||
if ( $is_prefix ) {
|
||||
if ( ! is_string( $attribute_name ) || ! preg_match( '/^[a-z][a-z0-9._:-]*-$/', $attribute_name ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $attribute_name . '*';
|
||||
}
|
||||
|
||||
if ( ! is_string( $attribute_name ) || ! preg_match( '/^[a-z][a-z0-9._:-]*$/', $attribute_name ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $attribute_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether an attribute name can be rendered for a field type.
|
||||
*
|
||||
* @param string $attribute_name Normalized attribute name.
|
||||
* @param string $field_type Normalized field type.
|
||||
* @param array $allowed_attributes Allowed attribute names and prefix markers.
|
||||
* @return bool
|
||||
*/
|
||||
private static function is_allowed_html_attribute( $attribute_name, $field_type, $allowed_attributes ) {
|
||||
if ( '' === $attribute_name ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
in_array( $attribute_name, self::$reserved_html_attributes, true ) ||
|
||||
0 === strpos( $attribute_name, 'on' ) ||
|
||||
0 === strpos( $attribute_name, 'form' ) ||
|
||||
0 === strpos( $attribute_name, 'data-gb-' )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$is_allowed = false;
|
||||
|
||||
foreach ( $allowed_attributes as $allowed_attribute ) {
|
||||
if ( '-*' === substr( $allowed_attribute, -2 ) ) {
|
||||
$prefix = substr( $allowed_attribute, 0, -1 );
|
||||
|
||||
if ( 0 === strpos( $attribute_name, $prefix ) ) {
|
||||
$is_allowed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( $attribute_name === $allowed_attribute ) {
|
||||
$is_allowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $is_allowed ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
isset( self::$html_attribute_field_type_support[ $attribute_name ] ) &&
|
||||
! in_array( $field_type, self::$html_attribute_field_type_support[ $attribute_name ], true )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sanitized custom HTML attributes for a control block.
|
||||
*
|
||||
* @param array $attributes Block attributes.
|
||||
* @param string $field_type Normalized field type.
|
||||
* @return array
|
||||
*/
|
||||
private static function get_custom_html_attributes( $attributes, $field_type ) {
|
||||
return self::sanitize_html_attributes( $attributes['htmlAttributes'] ?? [], $field_type );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the Form Field Control block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param WP_Block $block The block instance.
|
||||
* @return string
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
unset( $block_content );
|
||||
|
||||
$field_type = GenerateBlocks_Block_Form_Field::normalize_field_type(
|
||||
GenerateBlocks_Block_Form_Field::get_context_value( $block, 'fieldType', '' )
|
||||
);
|
||||
$field_name = sanitize_key(
|
||||
GenerateBlocks_Block_Form_Field::get_context_value( $block, 'fieldName', '' )
|
||||
);
|
||||
$unique_id = (string) GenerateBlocks_Block_Form_Field::get_context_value( $block, 'uniqueId', '' );
|
||||
$required = 'hidden' !== $field_type && ! empty( GenerateBlocks_Block_Form_Field::get_context_value( $block, 'isRequired', false ) );
|
||||
$field_id = GenerateBlocks_Block_Form_Field::get_field_id( $unique_id, $field_name );
|
||||
$html = self::build_control( $attributes, $field_type, $field_name, $field_id, $required, $block );
|
||||
|
||||
return generateblocks_maybe_add_block_css(
|
||||
$html,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the control markup.
|
||||
*
|
||||
* @param array $attributes Block attributes.
|
||||
* @param string $field_type Field type.
|
||||
* @param string $field_name Field name.
|
||||
* @param string $field_id Field ID.
|
||||
* @param bool $required Whether required.
|
||||
* @param mixed $block Block instance.
|
||||
* @return string
|
||||
*/
|
||||
private static function build_control( $attributes, $field_type, $field_name, $field_id, $required, $block ) {
|
||||
$default_value = GenerateBlocks_Block_Form_Field::resolve_default_value( $attributes['defaultValue'] ?? '', $block );
|
||||
|
||||
switch ( $field_type ) {
|
||||
case 'textarea':
|
||||
return self::build_textarea( $attributes, $field_name, $field_id, $required, $default_value );
|
||||
|
||||
case 'select':
|
||||
return self::build_select( $attributes, $field_name, $field_id, $required, $default_value );
|
||||
|
||||
case 'checkbox':
|
||||
return self::build_checkbox( $attributes, $field_name, $field_id, $required );
|
||||
|
||||
case 'radio':
|
||||
return self::build_choice_group( $attributes, $field_name, $field_id, true, $required, $default_value );
|
||||
|
||||
case 'checkbox-group':
|
||||
return self::build_choice_group( $attributes, $field_name, $field_id, false, false, '' );
|
||||
|
||||
default:
|
||||
return self::build_input( $attributes, $field_name, $field_id, $field_type, $required, $default_value );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build base control classes.
|
||||
*
|
||||
* @param array $attributes Block attributes.
|
||||
* @param string $element Element class.
|
||||
* @return string
|
||||
*/
|
||||
private static function get_control_classes( $attributes, $element ) {
|
||||
return GenerateBlocks_Block_Form_Field::get_block_classes(
|
||||
'gb-form-field-control',
|
||||
$attributes,
|
||||
[ $element ]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an input element.
|
||||
*
|
||||
* @param array $attributes Block attributes.
|
||||
* @param string $name Field name.
|
||||
* @param string $id Field ID.
|
||||
* @param string $type Input type.
|
||||
* @param bool $required Whether required.
|
||||
* @param string $default_value Default value.
|
||||
* @return string
|
||||
*/
|
||||
private static function build_input( $attributes, $name, $id, $type, $required, $default_value ) {
|
||||
$attrs = array_merge(
|
||||
self::get_custom_html_attributes( $attributes, $type ),
|
||||
[
|
||||
'class' => self::get_control_classes( $attributes, 'gb-form-field__input' ),
|
||||
'type' => $type,
|
||||
'name' => $name,
|
||||
'id' => $id,
|
||||
]
|
||||
);
|
||||
|
||||
if ( ! empty( $attributes['placeholder'] ) && 'hidden' !== $type ) {
|
||||
$attrs['placeholder'] = (string) $attributes['placeholder'];
|
||||
}
|
||||
|
||||
if ( '' !== $default_value ) {
|
||||
$attrs['value'] = $default_value;
|
||||
}
|
||||
|
||||
if ( $required ) {
|
||||
$attrs['required'] = true;
|
||||
$attrs['aria-required'] = 'true';
|
||||
}
|
||||
|
||||
return self::single_tag( 'input', $attrs );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a textarea element.
|
||||
*
|
||||
* @param array $attributes Block attributes.
|
||||
* @param string $name Field name.
|
||||
* @param string $id Field ID.
|
||||
* @param bool $required Whether required.
|
||||
* @param string $default_value Default value.
|
||||
* @return string
|
||||
*/
|
||||
private static function build_textarea( $attributes, $name, $id, $required, $default_value ) {
|
||||
$attrs = array_merge(
|
||||
self::get_custom_html_attributes( $attributes, 'textarea' ),
|
||||
[
|
||||
'class' => self::get_control_classes( $attributes, 'gb-form-field__input' ),
|
||||
'name' => $name,
|
||||
'id' => $id,
|
||||
]
|
||||
);
|
||||
$rows = isset( $attributes['rows'] ) ? min( self::MAX_TEXTAREA_ROWS, absint( $attributes['rows'] ) ) : 0;
|
||||
|
||||
if ( $rows ) {
|
||||
$attrs['rows'] = $rows;
|
||||
}
|
||||
|
||||
if ( ! empty( $attributes['placeholder'] ) ) {
|
||||
$attrs['placeholder'] = (string) $attributes['placeholder'];
|
||||
}
|
||||
|
||||
if ( $required ) {
|
||||
$attrs['required'] = true;
|
||||
$attrs['aria-required'] = 'true';
|
||||
}
|
||||
|
||||
return self::wrap_tag( 'textarea', $attrs, esc_textarea( $default_value ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a select element.
|
||||
*
|
||||
* @param array $attributes Block attributes.
|
||||
* @param string $name Field name.
|
||||
* @param string $id Field ID.
|
||||
* @param bool $required Whether required.
|
||||
* @param string $default_value Default selected value.
|
||||
* @return string
|
||||
*/
|
||||
private static function build_select( $attributes, $name, $id, $required, $default_value ) {
|
||||
$attrs = array_merge(
|
||||
self::get_custom_html_attributes( $attributes, 'select' ),
|
||||
[
|
||||
'class' => self::get_control_classes( $attributes, 'gb-form-field__input' ),
|
||||
'name' => $name,
|
||||
'id' => $id,
|
||||
]
|
||||
);
|
||||
|
||||
if ( $required ) {
|
||||
$attrs['required'] = true;
|
||||
$attrs['aria-required'] = 'true';
|
||||
}
|
||||
|
||||
$options_html = '';
|
||||
$placeholder = $attributes['placeholder'] ?? '';
|
||||
|
||||
if ( '' !== $placeholder ) {
|
||||
$options_html .= sprintf(
|
||||
'<option value="" disabled%s>%s</option>',
|
||||
'' === $default_value ? ' selected' : '',
|
||||
esc_html( $placeholder )
|
||||
);
|
||||
}
|
||||
|
||||
foreach ( (array) ( $attributes['options'] ?? [] ) as $option ) {
|
||||
$option = GenerateBlocks_Block_Form_Field::normalize_option( $option );
|
||||
|
||||
if ( ! $option ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$options_html .= sprintf(
|
||||
'<option value="%s"%s>%s</option>',
|
||||
esc_attr( $option['value'] ),
|
||||
'' !== $default_value && $option['value'] === $default_value ? ' selected' : '',
|
||||
esc_html( $option['label'] )
|
||||
);
|
||||
}
|
||||
|
||||
return self::wrap_tag( 'select', $attrs, $options_html );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a checkbox element.
|
||||
*
|
||||
* @param array $attributes Block attributes.
|
||||
* @param string $name Field name.
|
||||
* @param string $id Field ID.
|
||||
* @param bool $required Whether required.
|
||||
* @return string
|
||||
*/
|
||||
private static function build_checkbox( $attributes, $name, $id, $required ) {
|
||||
$checked_value = ! empty( $attributes['checkedValue'] )
|
||||
? sanitize_text_field( (string) $attributes['checkedValue'] )
|
||||
: 'yes';
|
||||
$attrs = array_merge(
|
||||
self::get_custom_html_attributes( $attributes, 'checkbox' ),
|
||||
[
|
||||
'class' => self::get_control_classes( $attributes, 'gb-form-field__input' ),
|
||||
'type' => 'checkbox',
|
||||
'name' => $name,
|
||||
'id' => $id,
|
||||
'value' => $checked_value,
|
||||
]
|
||||
);
|
||||
|
||||
if ( $required ) {
|
||||
$attrs['required'] = true;
|
||||
$attrs['aria-required'] = 'true';
|
||||
}
|
||||
|
||||
return self::single_tag( 'input', $attrs );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build radio/checkbox-group options.
|
||||
*
|
||||
* @param array $attributes Block attributes.
|
||||
* @param string $name Field name.
|
||||
* @param string $id Field ID prefix.
|
||||
* @param bool $radio Whether radio buttons.
|
||||
* @param bool $required Whether radio group is required.
|
||||
* @param string $default_value Default selected value.
|
||||
* @return string
|
||||
*/
|
||||
private static function build_choice_group( $attributes, $name, $id, $radio, $required, $default_value ) {
|
||||
$attrs = [
|
||||
'class' => self::get_control_classes( $attributes, 'gb-form-field__group' ),
|
||||
];
|
||||
$html = '';
|
||||
|
||||
foreach ( (array) ( $attributes['options'] ?? [] ) as $index => $option ) {
|
||||
$option = GenerateBlocks_Block_Form_Field::normalize_option( $option );
|
||||
|
||||
if ( ! $option ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$option_id = $id . '-' . $index;
|
||||
$html .= sprintf(
|
||||
'<label class="gb-form-field__group-option" for="%s">',
|
||||
esc_attr( $option_id )
|
||||
);
|
||||
|
||||
$input_attrs = [
|
||||
'type' => $radio ? 'radio' : 'checkbox',
|
||||
'name' => $radio ? $name : $name . '[]',
|
||||
'id' => $option_id,
|
||||
'value' => $option['value'],
|
||||
];
|
||||
|
||||
if ( $radio && '' !== $default_value && $option['value'] === $default_value ) {
|
||||
$input_attrs['checked'] = true;
|
||||
}
|
||||
|
||||
if ( $radio && $required ) {
|
||||
$input_attrs['required'] = true;
|
||||
}
|
||||
|
||||
$html .= '<input ' . GenerateBlocks_Block_Form_Field::format_attributes( $input_attrs ) . ' />';
|
||||
$html .= '<span>' . esc_html( $option['label'] ) . '</span>';
|
||||
$html .= '</label>';
|
||||
}
|
||||
|
||||
return self::wrap_tag( 'div', $attrs, $html );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a single tag.
|
||||
*
|
||||
* @param string $tag Tag name.
|
||||
* @param array $attrs Generated attributes.
|
||||
* @return string
|
||||
*/
|
||||
private static function single_tag( $tag, $attrs ) {
|
||||
$attr_string = GenerateBlocks_Block_Form_Field::format_attributes( $attrs );
|
||||
|
||||
return sprintf( '<%s %s />', tag_escape( $tag ), $attr_string );
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an element with content.
|
||||
*
|
||||
* @param string $tag Tag name.
|
||||
* @param array $attrs Generated attributes.
|
||||
* @param string $content Inner HTML.
|
||||
* @return string
|
||||
*/
|
||||
private static function wrap_tag( $tag, $attrs, $content ) {
|
||||
$attr_string = GenerateBlocks_Block_Form_Field::format_attributes( $attrs );
|
||||
|
||||
return sprintf(
|
||||
'<%1$s %2$s>%3$s</%1$s>',
|
||||
tag_escape( $tag ),
|
||||
$attr_string,
|
||||
$content
|
||||
);
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* Register the Form Field Control block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/class-form-field-control.php';
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Form Field Label block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form field label block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Form_Field_Label extends GenerateBlocks_Block {
|
||||
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Block name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/form-field-label';
|
||||
|
||||
/**
|
||||
* Render the Form Field Label block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param WP_Block $block The block instance.
|
||||
* @return string
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
$field_type = GenerateBlocks_Block_Form_Field::normalize_field_type(
|
||||
GenerateBlocks_Block_Form_Field::get_context_value( $block, 'fieldType', '' )
|
||||
);
|
||||
|
||||
if ( 'hidden' === $field_type ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$field_name = (string) GenerateBlocks_Block_Form_Field::get_context_value( $block, 'fieldName', '' );
|
||||
$unique_id = (string) GenerateBlocks_Block_Form_Field::get_context_value( $block, 'uniqueId', '' );
|
||||
$required = ! empty( GenerateBlocks_Block_Form_Field::get_context_value( $block, 'isRequired', false ) );
|
||||
$is_group = GenerateBlocks_Block_Form_Field::is_group_type( $field_type );
|
||||
|
||||
$has_content = '' !== trim( wp_strip_all_tags( (string) ( $attributes['content'] ?? '' ) ) );
|
||||
|
||||
if ( ! $has_content ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
if ( class_exists( 'WP_HTML_Tag_Processor' ) ) {
|
||||
$processor = new WP_HTML_Tag_Processor( $block_content );
|
||||
$tag_name = $is_group ? 'legend' : 'label';
|
||||
|
||||
if ( $processor->next_tag( $tag_name ) ) {
|
||||
if ( ! $is_group ) {
|
||||
$processor->set_attribute( 'for', GenerateBlocks_Block_Form_Field::get_field_id( $unique_id, $field_name ) );
|
||||
}
|
||||
|
||||
$block_content = $processor->get_updated_html();
|
||||
}
|
||||
}
|
||||
|
||||
return $required ? self::append_required_marker( $block_content, $is_group ? 'legend' : 'label' ) : $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the runtime required marker inside the saved label/legend markup.
|
||||
*
|
||||
* @param string $html Label block HTML.
|
||||
* @param string $tag_name Label tag name.
|
||||
* @return string
|
||||
*/
|
||||
private static function append_required_marker( $html, $tag_name ) {
|
||||
if ( false !== strpos( $html, 'gb-form-field__required' ) ) {
|
||||
return $html;
|
||||
}
|
||||
|
||||
$tag_name = tag_escape( $tag_name );
|
||||
$updated = preg_replace(
|
||||
sprintf( '#</%s>\s*$#i', preg_quote( $tag_name, '#' ) ),
|
||||
'<span class="gb-form-field__required" aria-hidden="true"> *</span></' . $tag_name . '>',
|
||||
$html,
|
||||
1
|
||||
);
|
||||
|
||||
return is_string( $updated ) ? $updated : $html;
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* Register the Form Field Label block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/class-form-field-label.php';
|
||||
+395
@@ -0,0 +1,395 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Form Field wrapper block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form field wrapper block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Form_Field extends GenerateBlocks_Block {
|
||||
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Block name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/form-field';
|
||||
|
||||
/**
|
||||
* All allowed field types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $allowed_types = [ 'text', 'email', 'url', 'tel', 'number', 'hidden', 'textarea', 'select', 'checkbox', 'radio', 'checkbox-group' ];
|
||||
|
||||
/**
|
||||
* Field types that support same-value match validation.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $matchable_types = [ 'text', 'email', 'url', 'tel', 'number', 'textarea' ];
|
||||
|
||||
/**
|
||||
* Allowed display condition operators.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $allowed_condition_operators = [ 'is', 'isnot', 'isempty', 'isnotempty' ];
|
||||
|
||||
/**
|
||||
* Per-render instance number, set by GenerateBlocks_Pro_Form_Render before
|
||||
* rendering each form.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private static $render_instance = 0;
|
||||
|
||||
/**
|
||||
* Set the current render instance number.
|
||||
*
|
||||
* @param int $instance Instance number (1+) or 0 to reset.
|
||||
*/
|
||||
public static function set_render_instance( $instance ) {
|
||||
self::$render_instance = (int) $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current render instance number.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function get_render_instance() {
|
||||
return (int) self::$render_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Suffix appended to every field ID for the current render.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function id_suffix() {
|
||||
return self::$render_instance > 0 ? '-' . self::$render_instance : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a field type.
|
||||
*
|
||||
* @param mixed $field_type Raw field type.
|
||||
* @return string
|
||||
*/
|
||||
public static function normalize_field_type( $field_type ) {
|
||||
$field_type = is_string( $field_type ) ? $field_type : '';
|
||||
|
||||
if ( '' === $field_type ) {
|
||||
return 'text';
|
||||
}
|
||||
|
||||
if ( ! in_array( $field_type, self::$allowed_types, true ) ) {
|
||||
return 'text';
|
||||
}
|
||||
|
||||
return $field_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a field type uses the wrapper as a fieldset.
|
||||
*
|
||||
* @param string $field_type Field type.
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_group_type( $field_type ) {
|
||||
return in_array( self::normalize_field_type( $field_type ), [ 'radio', 'checkbox-group' ], true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a field ID shared by label/control children.
|
||||
*
|
||||
* @param string $unique_id Wrapper unique ID.
|
||||
* @param string $field_name Field name fallback.
|
||||
* @return string
|
||||
*/
|
||||
public static function get_field_id( $unique_id, $field_name = '' ) {
|
||||
$key = $unique_id ? $unique_id : sanitize_key( $field_name );
|
||||
|
||||
if ( '' === $key ) {
|
||||
$key = 'field';
|
||||
}
|
||||
|
||||
return 'gb-field-' . sanitize_html_class( $key ) . self::id_suffix();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a value from a WP_Block context object.
|
||||
*
|
||||
* @param mixed $block Block object.
|
||||
* @param string $key Context key suffix.
|
||||
* @param mixed $fallback Fallback.
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get_context_value( $block, $key, $fallback = '' ) {
|
||||
$context_key = 'generateblocks-pro/form-field/' . $key;
|
||||
|
||||
if ( is_object( $block ) && isset( $block->context ) && is_array( $block->context ) && array_key_exists( $context_key, $block->context ) ) {
|
||||
return $block->context[ $context_key ];
|
||||
}
|
||||
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build classes for a styles-builder-aware block.
|
||||
*
|
||||
* @param string $base_class Base class.
|
||||
* @param array $attributes Block attributes.
|
||||
* @param array $extra Extra classes.
|
||||
* @return string
|
||||
*/
|
||||
public static function get_block_classes( $base_class, $attributes, $extra = [] ) {
|
||||
$classes = [ $base_class ];
|
||||
|
||||
if ( ! empty( $attributes['globalClasses'] ) && is_array( $attributes['globalClasses'] ) ) {
|
||||
foreach ( $attributes['globalClasses'] as $class_name ) {
|
||||
$class_name = sanitize_html_class( $class_name );
|
||||
|
||||
if ( $class_name ) {
|
||||
$classes[] = $class_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $attributes['styles'] ) && is_array( $attributes['styles'] ) && ! empty( $attributes['uniqueId'] ) ) {
|
||||
$classes[] = $base_class . '-' . sanitize_html_class( $attributes['uniqueId'] );
|
||||
}
|
||||
|
||||
foreach ( $extra as $class_name ) {
|
||||
$class_name = sanitize_html_class( $class_name );
|
||||
|
||||
if ( $class_name ) {
|
||||
$classes[] = $class_name;
|
||||
}
|
||||
}
|
||||
|
||||
return implode( ' ', array_unique( array_filter( $classes ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Format an associative attribute array.
|
||||
*
|
||||
* @param array $attributes Attribute name/value pairs.
|
||||
* @return string
|
||||
*/
|
||||
public static function format_attributes( $attributes ) {
|
||||
$out = [];
|
||||
|
||||
foreach ( $attributes as $name => $value ) {
|
||||
if ( true === $value ) {
|
||||
$out[] = esc_attr( $name );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( false === $value || null === $value || is_array( $value ) || is_object( $value ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$out[] = sprintf( '%s="%s"', esc_attr( $name ), esc_attr( (string) $value ) );
|
||||
}
|
||||
|
||||
return implode( ' ', $out );
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a choice option for rendering.
|
||||
*
|
||||
* @param mixed $option Raw option attribute.
|
||||
* @return array|null Normalized label/value pair or null for empty rows.
|
||||
*/
|
||||
public static function normalize_option( $option ) {
|
||||
if ( ! is_array( $option ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$label = isset( $option['label'] ) ? (string) $option['label'] : '';
|
||||
$value = isset( $option['value'] ) ? (string) $option['value'] : '';
|
||||
|
||||
if ( '' === $value && '' !== $label ) {
|
||||
$value = $label;
|
||||
}
|
||||
|
||||
if ( '' === $label && '' !== $value ) {
|
||||
$label = $value;
|
||||
}
|
||||
|
||||
if ( '' === $label && '' === $value ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'label' => $label,
|
||||
'value' => $value,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize display conditions before rendering them as frontend data attrs.
|
||||
*
|
||||
* Incomplete rows can be left behind while editing, especially if a trigger
|
||||
* field is removed before the empty row is deleted. Those must not create
|
||||
* `data-gb-conditions`, because an empty field name evaluates as empty on the
|
||||
* frontend and causes a hidden-then-revealed layout shift.
|
||||
*
|
||||
* @param mixed $conditions Raw conditions attribute.
|
||||
* @return array
|
||||
*/
|
||||
private static function sanitize_conditions( $conditions ) {
|
||||
if ( ! is_array( $conditions ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$sanitized = [];
|
||||
|
||||
foreach ( $conditions as $condition ) {
|
||||
if ( ! is_array( $condition ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$field = sanitize_key( $condition['field'] ?? '' );
|
||||
$operator = sanitize_key( $condition['operator'] ?? '' );
|
||||
|
||||
if ( '' === $field || ! in_array( $operator, self::$allowed_condition_operators, true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sanitized[] = [
|
||||
'field' => $field,
|
||||
'operator' => $operator,
|
||||
'value' => (string) ( $condition['value'] ?? '' ),
|
||||
];
|
||||
}
|
||||
|
||||
return $sanitized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve dynamic tags in a default value.
|
||||
*
|
||||
* @param string $default_value Raw default value.
|
||||
* @param mixed $block Block instance.
|
||||
* @return string
|
||||
*/
|
||||
public static function resolve_default_value( $default_value, $block ) {
|
||||
$default_value = (string) $default_value;
|
||||
|
||||
if ( '' !== $default_value && false !== strpos( $default_value, '{{' ) && class_exists( 'GenerateBlocks_Register_Dynamic_Tag' ) ) {
|
||||
$default_value = GenerateBlocks_Register_Dynamic_Tag::replace_tags(
|
||||
$default_value,
|
||||
[],
|
||||
$block
|
||||
);
|
||||
}
|
||||
|
||||
return (string) $default_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the Form Field wrapper block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param WP_Block $block The block instance.
|
||||
* @return string The modified block content.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
unset( $block );
|
||||
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
$field_type = self::normalize_field_type( $attributes['fieldType'] ?? '' );
|
||||
|
||||
if ( ! class_exists( 'WP_HTML_Tag_Processor' ) ) {
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
$processor = new WP_HTML_Tag_Processor( $block_content );
|
||||
|
||||
$tag_name = self::is_group_type( $field_type ) ? 'fieldset' : 'div';
|
||||
|
||||
if ( ! $processor->next_tag( $tag_name ) ) {
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
$modifier_map = [
|
||||
'checkbox' => 'gb-form-field--checkbox',
|
||||
'radio' => 'gb-form-field--radio',
|
||||
'checkbox-group' => 'gb-form-field--checkbox-group',
|
||||
];
|
||||
|
||||
if ( isset( $modifier_map[ $field_type ] ) ) {
|
||||
$processor->add_class( $modifier_map[ $field_type ] );
|
||||
}
|
||||
|
||||
// The wrapper is a native <fieldset>, whose implicit "group" role does not
|
||||
// support aria-required (Lighthouse/axe: aria-allowed-attr). The required
|
||||
// state is carried by the native `required` attribute on the radio inputs;
|
||||
// checkbox groups have no native per-input required, so they validate via
|
||||
// data-gb-required + JS. Either way the <fieldset> needs no aria-required.
|
||||
if ( 'checkbox-group' === $field_type && ! empty( $attributes['isRequired'] ) ) {
|
||||
$processor->set_attribute( 'data-gb-required', 'true' );
|
||||
}
|
||||
|
||||
$field_name = sanitize_key( $attributes['fieldName'] ?? '' );
|
||||
$matches_field = sanitize_key( $attributes['matchesField'] ?? '' );
|
||||
|
||||
if (
|
||||
$field_name &&
|
||||
$matches_field &&
|
||||
$field_name !== $matches_field &&
|
||||
in_array( $field_type, self::$matchable_types, true )
|
||||
) {
|
||||
$processor->set_attribute( 'data-gb-field-name', $field_name );
|
||||
$processor->set_attribute( 'data-gb-matches-field', $matches_field );
|
||||
$processor->set_attribute(
|
||||
'data-gb-match-message',
|
||||
__( 'The matching fields must have the same value.', 'generateblocks-pro' )
|
||||
);
|
||||
$processor->set_attribute(
|
||||
'data-gb-match-message-with-label',
|
||||
/* translators: %1$s: source field label, %2$s: target field label. */
|
||||
__( 'Please make sure "%1$s" matches "%2$s".', 'generateblocks-pro' )
|
||||
);
|
||||
$processor->set_attribute(
|
||||
'data-gb-match-message-with-target',
|
||||
/* translators: %s: target field label. */
|
||||
__( 'This field must match "%s".', 'generateblocks-pro' )
|
||||
);
|
||||
}
|
||||
|
||||
$conditions = self::sanitize_conditions( $attributes['conditions'] ?? [] );
|
||||
|
||||
if ( ! empty( $conditions ) ) {
|
||||
$processor->set_attribute( 'data-gb-conditions', wp_json_encode( $conditions ) );
|
||||
$processor->set_attribute( 'hidden', true );
|
||||
}
|
||||
|
||||
return $processor->get_updated_html();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* Form field block loader.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/class-form-field.php';
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
/**
|
||||
* Form Render block.
|
||||
*
|
||||
* Page-side reference. Carries `formId` (a `gblocks_form` post ID) plus
|
||||
* styling attributes; everything else (fields, actions, email, Turnstile,
|
||||
* success/error messages) lives on the form post itself.
|
||||
*
|
||||
* Render delegates to the shared render helper so editor preview and
|
||||
* public output stay byte-for-byte equivalent.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form Render block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Form_Render extends GenerateBlocks_Block {
|
||||
|
||||
/**
|
||||
* Block name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/form-render';
|
||||
|
||||
/**
|
||||
* Render the Form Render block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param WP_Block $block The block instance.
|
||||
* @return string The modified block content.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
unset( $block_content );
|
||||
|
||||
$form_id = absint( $attributes['formId'] ?? 0 );
|
||||
|
||||
if ( ! $form_id ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$host_post_id = $block->context['postId'] ?? get_the_ID();
|
||||
$host_post_id = $host_post_id ? absint( $host_post_id ) : 0;
|
||||
|
||||
$rendered = GenerateBlocks_Pro_Form_Render::render( $form_id, 'public', [ 'host_post_id' => $host_post_id ] );
|
||||
|
||||
if ( is_wp_error( $rendered ) ) {
|
||||
// Public render failure — emit nothing rather than leaking error
|
||||
// detail. Admin users see a placeholder hint to help debugging.
|
||||
if ( current_user_can( GenerateBlocks_Pro_Form_Post_Type::get_capability( 'manage' ) ) ) {
|
||||
return sprintf(
|
||||
'<div class="gb-form gb-form--missing">%s</div>',
|
||||
esc_html__( 'Form not available. Make sure the referenced form is published.', 'generateblocks-pro' )
|
||||
);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
GenerateBlocks_Pro_Form_Render::enqueue_public_assets();
|
||||
|
||||
return $rendered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue block assets.
|
||||
*/
|
||||
public static function enqueue_assets() {
|
||||
GenerateBlocks_Pro_Form_Render::enqueue_public_assets();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* Form Render block loader.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/class-form-render.php';
|
||||
|
||||
add_filter( 'block_editor_settings_all', 'generateblocks_pro_form_block_editor_settings', 20 );
|
||||
/**
|
||||
* Add block editor settings for the form blocks.
|
||||
*
|
||||
* @param array $settings The block editor settings.
|
||||
*/
|
||||
function generateblocks_pro_form_block_editor_settings( $settings ) {
|
||||
$blocks_to_reset = [
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-form-render',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-form',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-form-field',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-form-field-label',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-form-field-control',
|
||||
];
|
||||
$css = implode( ',', $blocks_to_reset ) . ' {max-width:unset;margin:0}';
|
||||
$settings['styles'][] = [ 'css' => $css ];
|
||||
|
||||
return $settings;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* Form block.
|
||||
*
|
||||
* Authoring container that lives inside `gblocks_form` post content. Renders
|
||||
* its inner form-field blocks with our standard wrapper class. Runtime
|
||||
* action/method/security attributes are added by class-form-render.php while
|
||||
* a saved form post is being rendered.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Form extends GenerateBlocks_Block {
|
||||
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Block name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/form';
|
||||
|
||||
/**
|
||||
* Render the Form block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param WP_Block $block The block instance.
|
||||
* @return string The modified block content.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
unset( $block );
|
||||
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
if ( class_exists( 'GenerateBlocks_Pro_Form_Render' ) ) {
|
||||
return GenerateBlocks_Pro_Form_Render::prepare_form_block_output( $block_content );
|
||||
}
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* Form block loader.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/class-form.php';
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Content block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Content block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Menu_Container extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/menu-container';
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
/**
|
||||
* Handle the menu container block.
|
||||
*
|
||||
* @package GenerateBlocks Pro
|
||||
*/
|
||||
|
||||
// Include our files.
|
||||
require_once 'class-menu-container.php';
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Content block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Content block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Menu_Toggle extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/menu-toggle';
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
/**
|
||||
* Handle the menu toggle block.
|
||||
*
|
||||
* @package GenerateBlocks Pro
|
||||
*/
|
||||
|
||||
// Include our files.
|
||||
require_once 'class-menu-toggle.php';
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Content block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Content block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Navigation extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/navigation';
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* Handle the navigation block.
|
||||
*
|
||||
* @package GenerateBlocks Pro
|
||||
*/
|
||||
|
||||
// Include our files.
|
||||
require_once 'class-navigation.php';
|
||||
|
||||
add_filter( 'block_editor_settings_all', 'generateblocks_pro_navigation_block_editor_settings', 20 );
|
||||
/**
|
||||
* Add block editor settings for the navigation block.
|
||||
*
|
||||
* @param array $settings The block editor settings.
|
||||
*/
|
||||
function generateblocks_pro_navigation_block_editor_settings( $settings ) {
|
||||
$blocks_to_reset = [
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-classic-menu',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-menu-container',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-menu-toggle',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-navigation',
|
||||
];
|
||||
$css = implode( ',', $blocks_to_reset ) . ' {max-width:unset;margin:0}';
|
||||
$settings['styles'][] = [ 'css' => $css ];
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
add_filter( 'generateblocks_block_css', 'generateblocks_pro_navigation_block_css', 10, 2 );
|
||||
/**
|
||||
* Add block CSS for the navigation block.
|
||||
*
|
||||
* @param string $css The CSS to add.
|
||||
* @param array $block The block data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function generateblocks_pro_navigation_block_css( $css, $block ) {
|
||||
if ( ! isset( $block['attributes']['uniqueId'] ) ) {
|
||||
return $css;
|
||||
}
|
||||
|
||||
$block_name = $block['block_name'] ?? '';
|
||||
|
||||
if ( 'generateblocks-pro/navigation' !== $block_name ) {
|
||||
return $css;
|
||||
}
|
||||
|
||||
$selector = '.gb-navigation-' . $block['attributes']['uniqueId'];
|
||||
|
||||
$mobile_breakpoint = $block['attributes']['htmlAttributes']['data-gb-mobile-breakpoint'] ?? '';
|
||||
|
||||
if ( $mobile_breakpoint ) {
|
||||
$css .= "@media (width > {$mobile_breakpoint}) {{$selector} .gb-menu-toggle {display: none;}}";
|
||||
$css .= "@media (max-width: {$mobile_breakpoint}) {{$selector} .gb-menu-container:not(.gb-menu-container--toggled) {display: none;}}";
|
||||
} else {
|
||||
$css .= "{$selector} .gb-menu-toggle {display: none;}";
|
||||
}
|
||||
|
||||
return $css;
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Content block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Content block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Site_Header extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/site-header';
|
||||
|
||||
/**
|
||||
* Store when to enqueue assets.
|
||||
*
|
||||
* @var array $assets_to_enqueue The assets to enqueue.
|
||||
*/
|
||||
public static $assets_to_enqueue = [];
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
$html_attributes = $attributes['htmlAttributes'] ?? [];
|
||||
$is_sticky = array_key_exists( 'data-gb-is-sticky', $html_attributes );
|
||||
|
||||
if ( $is_sticky ) {
|
||||
wp_enqueue_script(
|
||||
'generateblocks-pro-sticky',
|
||||
GENERATEBLOCKS_PRO_DIR_URL . 'dist/sticky-element.js',
|
||||
[],
|
||||
GENERATEBLOCKS_PRO_VERSION,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* Handle the navigation block.
|
||||
*
|
||||
* @package GenerateBlocks Pro
|
||||
*/
|
||||
|
||||
// Include our files.
|
||||
require_once 'class-site-header.php';
|
||||
|
||||
add_filter( 'block_editor_settings_all', 'generateblocks_pro_site_header_block_editor_settings', 20 );
|
||||
/**
|
||||
* Add block editor settings for the navigation block.
|
||||
*
|
||||
* @param array $settings The block editor settings.
|
||||
*/
|
||||
function generateblocks_pro_site_header_block_editor_settings( $settings ) {
|
||||
$blocks_to_reset = [
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-site-header',
|
||||
];
|
||||
$css = implode( ',', $blocks_to_reset ) . ' {max-width:unset;margin:0}';
|
||||
$settings['styles'][] = [ 'css' => $css ];
|
||||
|
||||
return $settings;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Tab Item block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Tabs menu block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Tab_Item extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/tab-item';
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
if ( $attributes['tabItemOpen'] ) {
|
||||
$processor = class_exists( 'WP_HTML_Tag_Processor' )
|
||||
? new WP_HTML_Tag_Processor( $block_content )
|
||||
: false;
|
||||
|
||||
if ( $processor && $processor->next_tag( $attributes['tagName'] ?? 'div' ) ) {
|
||||
$processor->add_class( 'gb-tabs__item-open' );
|
||||
$block_content = $processor->get_updated_html();
|
||||
}
|
||||
}
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Tab Items block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Tabs menu block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Tab_Items extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/tab-items';
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Tab Menu Item block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Tabs menu block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Tab_Menu_Item extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/tab-menu-item';
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
if ( ! class_exists( 'WP_HTML_Tag_Processor' ) ) {
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
$processor = new WP_HTML_Tag_Processor( $block_content );
|
||||
$tag_name = $attributes['tagName'] ?? 'div';
|
||||
$main_tag = $processor->next_tag( $tag_name );
|
||||
$updated_html = false;
|
||||
|
||||
if ( $processor && $main_tag ) {
|
||||
if ( $attributes['tabItemOpen'] ) {
|
||||
$processor->add_class( 'gb-block-is-current' );
|
||||
$updated_html = true;
|
||||
}
|
||||
|
||||
if ( 'div' === $tag_name ) {
|
||||
if ( ! $processor->get_attribute( 'tabindex' ) ) {
|
||||
$processor->set_attribute( 'tabindex', '0' );
|
||||
}
|
||||
|
||||
if ( ! $processor->get_attribute( 'role' ) ) {
|
||||
$processor->set_attribute( 'role', 'button' );
|
||||
}
|
||||
|
||||
$updated_html = true;
|
||||
}
|
||||
|
||||
if ( $updated_html ) {
|
||||
$block_content = $processor->get_updated_html();
|
||||
}
|
||||
}
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Tabs Menu block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Tabs menu block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Tabs_Menu extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/tabs-menu';
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the Tabs block.
|
||||
*
|
||||
* @package GenerateBlocksPro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Tabs block class.
|
||||
*/
|
||||
class GenerateBlocks_Block_Tabs extends GenerateBlocks_Block {
|
||||
/**
|
||||
* Keep track of all blocks of this type on the page.
|
||||
*
|
||||
* @var array $block_ids The current block id.
|
||||
*/
|
||||
protected static $block_ids = [];
|
||||
|
||||
/**
|
||||
* Store our block name.
|
||||
*
|
||||
* @var string $block_name The block name.
|
||||
*/
|
||||
public static $block_name = 'generateblocks-pro/tabs';
|
||||
|
||||
/**
|
||||
* Render the Element block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $block_content The block content.
|
||||
* @param array $block The block.
|
||||
*/
|
||||
public static function render_block( $attributes, $block_content, $block ) {
|
||||
// Add styles to this block if needed.
|
||||
$block_content = generateblocks_maybe_add_block_css(
|
||||
$block_content,
|
||||
[
|
||||
'class_name' => __CLASS__,
|
||||
'attributes' => $attributes,
|
||||
'block_ids' => self::$block_ids,
|
||||
]
|
||||
);
|
||||
|
||||
if ( ! wp_style_is( 'generateblocks-tabs', 'enqueued' ) ) {
|
||||
self::enqueue_style();
|
||||
}
|
||||
|
||||
if ( ! wp_script_is( 'generateblocks-tabs', 'enqueued' ) ) {
|
||||
self::enqueue_assets();
|
||||
}
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue block styles.
|
||||
*/
|
||||
private static function enqueue_style() {
|
||||
wp_enqueue_style(
|
||||
'generateblocks-tabs',
|
||||
GENERATEBLOCKS_PRO_DIR_URL . 'dist/blocks/tabs/tabs.css',
|
||||
[],
|
||||
GENERATEBLOCKS_PRO_VERSION
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue block scripts.
|
||||
*/
|
||||
private static function enqueue_scripts() {
|
||||
wp_enqueue_script(
|
||||
'generateblocks-tabs',
|
||||
GENERATEBLOCKS_PRO_DIR_URL . 'dist/tabs.js',
|
||||
[],
|
||||
GENERATEBLOCKS_PRO_VERSION,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue block assets.
|
||||
*/
|
||||
public static function enqueue_assets() {
|
||||
self::enqueue_scripts();
|
||||
self::enqueue_style();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* Handles the accordion block.
|
||||
*
|
||||
* @package GenerateBlocks Pro
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
require_once 'class-tabs.php';
|
||||
require_once 'class-tabs-menu.php';
|
||||
require_once 'class-tab-menu-item.php';
|
||||
require_once 'class-tab-items.php';
|
||||
require_once 'class-tab-item.php';
|
||||
|
||||
add_filter( 'block_editor_settings_all', 'generateblocks_pro_tabs_block_editor_settings', 20 );
|
||||
/**
|
||||
* Add block editor settings for the tabs block.
|
||||
*
|
||||
* @param array $settings The block editor settings.
|
||||
*/
|
||||
function generateblocks_pro_tabs_block_editor_settings( $settings ) {
|
||||
$blocks_to_reset = [
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-tabs',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-tabs-menu',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-tab-menu-item',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-tab-items',
|
||||
'.editor-styles-wrapper .wp-block-generateblocks-pro-tab-item',
|
||||
];
|
||||
$css = implode( ',', $blocks_to_reset ) . ' {max-width:unset;margin:0}';
|
||||
$settings['styles'][] = [ 'css' => $css ];
|
||||
|
||||
return $settings;
|
||||
}
|
||||
Reference in New Issue
Block a user