*/ private static array $stack = []; /** Test seam: reset the per-request state. */ public static function reset(): void { self::$stack = []; } public static function is_embeddable(int $id): bool { if ($id <= 0 || !function_exists('get_post_type')) { return false; } $type = get_post_type($id); if ($type === Store::CPT) { return true; } // Theme templates: sections of the site (header, footer, loop items ...) are fine; a popup is not a section. return $type === TemplatePost::POST_TYPE && (string) get_post_meta($id, TemplatePost::META_TYPE, true) !== 'popup'; } public static function can_view(int $id, bool $preview): bool { $post = get_post($id); if (!$post) { return false; } if (($post->post_status ?? '') === 'publish') { return true; } return $preview && current_user_can('edit_post', $id); } /** * HTML of the template's elements ('' when not embeddable, not visible or recursive). `$preview` = editor * preview (drafts allowed, element markers dropped). */ public static function render(int $id, Renderer $renderer, bool $preview = false): string { if (!self::is_embeddable($id) || !self::can_view($id, $preview) || isset(self::$stack[$id])) { return ''; } $host = function_exists('get_the_ID') ? (int) get_the_ID() : 0; if ($host === $id) { return ''; } self::$stack[$id] = true; try { $data = Document::get_data($id); $html = $renderer->render_document(is_array($data['elements'] ?? null) ? $data['elements'] : []); } finally { unset(self::$stack[$id]); } if ($preview) { $html = (string) preg_replace('/\sdata-zx-(?:id|type)="[^"]*"/', '', $html); } \Zadex\Frontend\Styles::document($id); return $html; } /** * Option list for the widget's select: library templates first, then theme templates (not popups), drafts * marked. The document being edited is left out. * * @return array */ public static function options(int $exclude = 0): array { $out = [['value' => '', 'label' => __('— Select —', 'zadex')]]; if (!function_exists('get_posts')) { return $out; } $groups = [ Store::CPT => __('Library', 'zadex'), TemplatePost::POST_TYPE => __('Theme template', 'zadex'), ]; foreach ($groups as $post_type => $group) { $posts = get_posts([ 'post_type' => $post_type, 'post_status' => ['publish', 'draft', 'private'], 'numberposts' => 200, 'orderby' => 'title', 'order' => 'ASC', ]); foreach (is_array($posts) ? $posts : [] as $post) { $id = (int) $post->ID; if ($id === $exclude || !self::is_embeddable($id)) { continue; } $title = (string) ($post->post_title ?? ''); $label = $group . ': ' . ($title !== '' ? $title : '#' . $id); if (($post->post_status ?? '') !== 'publish') { $label .= ' (' . __('draft', 'zadex') . ')'; } $out[] = ['value' => (string) $id, 'label' => $label]; } } return $out; } }