documents ) ) { $document = \Elementor\Plugin::$instance->documents->get_current(); if ( $document ) { return (int) $document->get_main_id(); } } return (int) get_the_ID(); } /** * Instance of the widget $widget_id (of type $widget_type) saved in the * Elementor document $post_id, with its saved settings applied. * * Returns null when the document is not published (unless the current * user may edit it), the widget does not exist or has another type. */ public static function get_widget( int $post_id, string $widget_id, string $widget_type ): ?\Elementor\Widget_Base { if ( ! $post_id || '' === $widget_id || ! class_exists( '\Elementor\Plugin' ) ) return null; $status = get_post_status( $post_id ); if ( ! $status ) return null; if ( 'publish' !== $status && ! current_user_can( 'edit_post', $post_id ) ) return null; if ( post_password_required( $post_id ) && ! current_user_can( 'edit_post', $post_id ) ) return null; $elementor = \Elementor\Plugin::$instance; if ( ! isset( $elementor->documents, $elementor->elements_manager ) ) return null; $document = $elementor->documents->get( $post_id ); if ( ! $document ) return null; $element = self::find_element( (array) $document->get_elements_data(), $widget_id ); // Elementor Pro "Global Widget": the real widget lives in a library template. if ( $element && 'global' === ( $element['widgetType'] ?? '' ) && ! empty( $element['templateID'] ) ) { $template = $elementor->documents->get( absint( $element['templateID'] ) ); $data = $template ? (array) $template->get_elements_data() : []; $element = isset( $data[0] ) && is_array( $data[0] ) ? $data[0] : null; } if ( ! $element || 'widget' !== ( $element['elType'] ?? '' ) || $widget_type !== ( $element['widgetType'] ?? '' ) ) { return null; } try { $widget = $elementor->elements_manager->create_element_instance( $element ); } catch ( \Throwable $e ) { eppro_log( 'EPP widget lookup error: ' . $e->getMessage() ); return null; } return $widget instanceof \Elementor\Widget_Base ? $widget : null; } /** Depth-first search for an element by ID in Elementor element data. */ private static function find_element( array $elements, string $id ): ?array { foreach ( $elements as $element ) { if ( ! is_array( $element ) ) continue; if ( isset( $element['id'] ) && (string) $element['id'] === $id ) { return $element; } if ( ! empty( $element['elements'] ) && is_array( $element['elements'] ) ) { $found = self::find_element( $element['elements'], $id ); if ( $found ) return $found; } } return null; } // ========================================================================= // Template rendering // ========================================================================= /** * Whether the current visitor may see the content of post $id when it is * embedded somewhere (template picker, shortcode, popup…): it must be * published and not password-protected, unless the user can edit it. */ public static function can_render( int $id ): bool { $post = get_post( $id ); if ( ! $post ) return false; if ( current_user_can( 'edit_post', $id ) ) return true; return 'publish' === $post->post_status && ! post_password_required( $post ); } /** * HTML of an Elementor template/page, or '' when it may not be shown. * * The markup is produced by Elementor, which escapes every widget's * output; running it through wp_kses_post() would strip SVG icons, form * inputs, iframes and inline