config_provider = is_callable( $config_provider ) ? $config_provider : null; } /** * Collect interactions from document elements during frontend render. * * This method is hooked to 'elementor/frontend/builder_content_data' filter * to capture interactions from all documents (header, footer, post content) * as they are rendered. * * @param array $elements_data The document's elements data. * @param int $post_id The document's post ID. * @return array The unmodified elements data (pass-through filter). */ public function collect_document_interactions( $elements_data, $post_id ) { // Only collect on frontend, not in editor if ( Plugin::$instance->editor->is_edit_mode() ) { return $elements_data; } if ( empty( $elements_data ) || ! is_array( $elements_data ) ) { return $elements_data; } $interactions_postmeta = new Interactions_Postmeta(); $cached_rows = $interactions_postmeta->load_content( $post_id ); if ( empty( $cached_rows ) ) { $cached_rows = $interactions_postmeta->process_content( $post_id, [ 'elements' => $elements_data, ] ); } $collector = Interactions_Collector::instance(); foreach ( $cached_rows as $element_id => $interactions ) { $collector->register( $element_id, $interactions ); } return $elements_data; } /** * Output collected interaction data as a JSON script tag in the footer. * * This method is hooked to 'wp_footer' to output all collected interactions * as a centralized JSON data block that the frontend JavaScript can consume. */ public function print_interactions_data() { // Only output on frontend, not in editor if ( Plugin::$instance->editor->is_edit_mode() ) { return; } $elements_with_interactions = $this->elements_with_interactions(); if ( empty( $elements_with_interactions ) ) { return; } $this->enqueue_interactions_assets(); // Output as JSON script tag $json_data = wp_json_encode( $elements_with_interactions, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- JSON data is already encoded echo ''; } private function elements_with_interactions() { $all_interactions = Interactions_Collector::instance()->get_all(); $elements_with_interactions = []; foreach ( $all_interactions as $element_id => $interactions ) { $elements_with_interactions[] = [ 'elementId' => $element_id, 'dataId' => $element_id, 'interactions' => $interactions, ]; } return $elements_with_interactions; } private function get_interactions_config() { return $this->config_provider ? call_user_func( $this->config_provider ) : []; } private function enqueue_interactions_assets() { wp_enqueue_script( Module::HANDLE_MOTION_JS ); wp_enqueue_script( Module::HANDLE_FRONTEND ); wp_localize_script( Module::HANDLE_FRONTEND, Module::JS_CONFIG_OBJECT, $this->get_interactions_config() ); } }