*/ private static $instance_ids = array(); /** * Per-placement recorder configs (server-trusted; keyed by data-dadan-record-root). * * @var array> */ private static $placement_configs = array(); /** * Register shortcode + late enqueue. */ public function register() { add_shortcode( 'dadan-recording', array( $this, 'render' ) ); add_shortcode( 'dadan_recording', array( $this, 'render' ) ); add_shortcode( 'dadan_record', array( $this, 'render' ) ); // Enqueue in head when possible; footer fallback after shortcode/block render. add_action( 'wp_enqueue_scripts', array( $this, 'maybe_enqueue' ), 20 ); add_action( 'wp_footer', array( $this, 'maybe_enqueue' ), 5 ); } /** * Mark that public recorder assets are needed for an instance. * * @param int $instance_id Instance post ID. */ public static function request_assets( $instance_id = 0 ) { self::$needs_assets = true; $instance_id = absint( $instance_id ); if ( $instance_id > 0 ) { self::$instance_ids[ $instance_id ] = $instance_id; } } /** * Register a placement config for wp_localize (credentials stay off the DOM trust path). * * @param string $uid data-dadan-record-root value. * @param array $config Recorder config from PHP. */ public static function register_placement( $uid, array $config ) { $uid = sanitize_html_class( (string) $uid ); if ( '' === $uid ) { return; } self::$placement_configs[ $uid ] = $config; self::$needs_assets = true; } /** * Placement configs for this request. * * @return array> */ public static function placement_configs() { return self::$placement_configs; } /** * Instance IDs collected for this request. * * @return array */ public static function requested_instance_ids() { return array_values( self::$instance_ids ); } /** * Whether public recorder assets were already localized this request. * * @return bool */ public static function assets_enqueued() { return self::$did_enqueue; } /** * Enqueue/localize now (late Elementor / AJAX). Safe to call repeatedly. */ public static function enqueue_now() { self::$needs_assets = true; if ( ! self::$did_enqueue ) { ( new self() )->maybe_enqueue(); return; } // Refresh localize so placements registered after the first enqueue are included (DADAN-25). $allowed_ids = array(); foreach ( self::$instance_ids as $id ) { $id = (int) $id; if ( $id && Dadan_Settings::visitor_can_record( $id ) ) { $allowed_ids[ $id ] = $id; } } self::$localized_placements = count( self::$placement_configs ); $recorder = new Dadan_Recorder(); $recorder->enqueue_recorder_assets( 'public', array_values( $allowed_ids ), self::$placement_configs ); } /** * Enqueue if shortcode/block rendered. */ public function maybe_enqueue() { if ( self::$did_enqueue ) { // Head enqueue ran before body widgets/blocks registered their placements // (e.g. Elementor widget on a page whose content also has [dadan_record]). if ( doing_action( 'wp_footer' ) && count( self::$placement_configs ) > self::$localized_placements ) { self::enqueue_now(); } return; } if ( ! self::$needs_assets && is_singular() ) { $post = get_post(); if ( $post instanceof WP_Post ) { $content = (string) $post->post_content; if ( has_shortcode( $content, 'dadan_record' ) || has_shortcode( $content, 'dadan-recording' ) || has_shortcode( $content, 'dadan_recording' ) || has_block( 'dadan/record', $post ) ) { self::$needs_assets = true; self::collect_ids_from_content( $content ); } } } if ( ! self::$needs_assets ) { return; } if ( empty( self::$instance_ids ) ) { $default = Dadan_Instance::default_id(); if ( $default && Dadan_Settings::visitor_can_record( $default ) ) { self::$instance_ids[ $default ] = $default; } } // DADAN-04: only ship instance configs the current visitor is allowed to use. $allowed_ids = array(); foreach ( self::$instance_ids as $id ) { $id = (int) $id; if ( $id && Dadan_Settings::visitor_can_record( $id ) ) { $allowed_ids[ $id ] = $id; } } // Placements are registered only after render() passed visitor_can_record. $placements = self::$placement_configs; if ( empty( $allowed_ids ) && empty( $placements ) ) { return; } self::$did_enqueue = true; self::$localized_placements = count( $placements ); $recorder = new Dadan_Recorder(); $recorder->enqueue_recorder_assets( 'public', array_values( $allowed_ids ), $placements ); wp_enqueue_style( 'dadan-video-public-record', DADAN_VIDEO_URL . 'assets/public-record.css', array(), DADAN_VIDEO_VERSION ); } /** * Pull instance ids from shortcodes in post content (early enqueue path). * * @param string $content Post content. */ private static function collect_ids_from_content( $content ) { if ( preg_match_all( '/\[(?:dadan-recording|dadan_recording|dadan_record)\b([^\]]*)\]/i', $content, $matches ) ) { foreach ( $matches[1] as $attr_str ) { $id = 0; if ( preg_match( '/\bid=["\']?(\d+)/i', $attr_str, $m ) ) { $id = absint( $m[1] ); } $id = Dadan_Instance::resolve_id( $id ); if ( $id ) { self::$instance_ids[ $id ] = $id; } } } if ( function_exists( 'parse_blocks' ) && has_block( 'dadan/record', $content ) ) { $blocks = parse_blocks( $content ); self::collect_ids_from_blocks( $blocks ); } } /** * @param array> $blocks Blocks. */ private static function collect_ids_from_blocks( $blocks ) { foreach ( $blocks as $block ) { if ( empty( $block['blockName'] ) ) { continue; } if ( 'dadan/record' === $block['blockName'] ) { $id = isset( $block['attrs']['instanceId'] ) ? absint( $block['attrs']['instanceId'] ) : 0; $id = Dadan_Instance::resolve_id( $id ); if ( $id ) { self::$instance_ids[ $id ] = $id; } } if ( ! empty( $block['innerBlocks'] ) && is_array( $block['innerBlocks'] ) ) { self::collect_ids_from_blocks( $block['innerBlocks'] ); } } } /** * Render [dadan-recording id="123"] / [dadan_record id="123" label="…"]. * * @param array|string $atts Attributes. * @return string */ public function render( $atts ) { $atts = shortcode_atts( array( 'id' => '', 'label' => '', ), $atts, 'dadan-recording' ); if ( ! Dadan_Recorder::bundle_ready() ) { return $this->editor_notice( __( 'Recorder unavailable. Reinstall the Dadan plugin or contact the site admin.', 'dadan' ) ); } $instance_id = Dadan_Instance::resolve_id( $atts['id'] ); if ( ! $instance_id || ! Dadan_Settings::can_record( $instance_id ) ) { return $this->editor_notice( __( 'Dadan recording is not configured. Add a Public App ID under Dadan → Instances.', 'dadan' ) ); } if ( ! Dadan_Settings::visitor_can_record( $instance_id ) ) { return $this->editor_notice( __( 'Recording is restricted on this site. Sign in with an allowed account, or ask an admin to change “Who can record on the site”.', 'dadan' ) ); } self::request_assets( $instance_id ); $uid = 'dadan-rec-' . wp_unique_id(); $label = sanitize_text_field( $atts['label'] ); $wrap = 'dadan-public-record'; if ( Dadan_Settings::cta_hide_on_phones( $instance_id ) ) { $wrap .= ' dadan-hide-on-phone'; } self::register_placement( $uid, Dadan_Settings::recorder_config( $instance_id ) ); ob_start(); ?>
$uid . '-btn', 'class' => 'dadan-record-trigger', 'label' => $label, 'instance_id' => $instance_id, ) ); echo wp_kses( $dadan_button_html, Dadan_Settings::kses_trigger_button() ); ?>

' . esc_html( $message ) . '

'; } }