false, 'html' => '', 'managed_html' => '', 'error' => $message, ]; } function samtyk_cmp_normalize_embed_identity(string $identity, string $source, array $categories): string { $normalized = strtolower(trim($identity)); $normalized = preg_replace('/[^a-z0-9_-]+/', '-', $normalized) ?: ''; $normalized = trim($normalized, '-_'); return $normalized !== '' ? $normalized : substr(hash('sha256', $source . '|' . implode(',', $categories)), 0, 12); } function samtyk_cmp_is_allowed_embed_attribute(string $name, string $tag): bool { if (strpos($name, 'data-') === 0 || strpos($name, 'aria-') === 0) { return true; } $attributes = [ 'script' => ['src', 'type', 'async', 'defer', 'crossorigin', 'integrity', 'referrerpolicy', 'nomodule'], 'iframe' => ['src', 'width', 'height', 'loading', 'allow', 'allowfullscreen', 'frameborder', 'referrerpolicy', 'scrolling', 'name', 'sandbox'], 'a' => ['href', 'target', 'rel'], 'img' => ['src', 'srcset', 'sizes', 'width', 'height', 'loading', 'alt', 'crossorigin', 'referrerpolicy'], 'source' => ['src', 'srcset', 'sizes', 'type', 'media'], 'video' => ['src', 'poster', 'width', 'height', 'controls', 'autoplay', 'loop', 'muted', 'playsinline', 'preload', 'crossorigin'], 'audio' => ['src', 'controls', 'autoplay', 'loop', 'muted', 'preload', 'crossorigin'], ]; return in_array($name, ['id', 'class', 'title', 'role', 'style', 'tabindex', 'dir', 'lang'], true) || in_array($name, $attributes[$tag] ?? [], true); } function samtyk_cmp_sanitize_embed_url(string $url, bool $is_link = false): string { $url = trim($url); if ($url === '' || preg_match('/[\x00-\x20\x7f\\\\]/', $url)) { return ''; } $protocols = $is_link ? ['http', 'https', 'mailto', 'tel'] : ['http', 'https']; $scheme = strtolower((string) wp_parse_url($url, PHP_URL_SCHEME)); if ($scheme !== '' && !in_array($scheme, $protocols, true)) { return ''; } if ($scheme === '' && !preg_match('~^(?:/|\./|\.\./|\?|\#)~', $url)) { // Preserve relative resource paths instead of esc_url_raw() adding a host/scheme. $url = './' . $url; } return esc_url_raw($url, $protocols); } function samtyk_cmp_sanitize_embed_srcset(string $srcset): string { $candidates = []; foreach (explode(',', $srcset) as $candidate) { $parts = preg_split('/\s+/', trim($candidate)); $url = samtyk_cmp_sanitize_embed_url($parts[0] ?? ''); if ($url === '' || count($parts) > 2 || (isset($parts[1]) && !preg_match('/^(?:[1-9][0-9]*w|(?:[0-9]+(?:\.[0-9]+)?)x)$/D', $parts[1]))) { return ''; } $candidates[] = $url . (isset($parts[1]) ? ' ' . $parts[1] : ''); } return implode(', ', $candidates); } /** Serialize validated elements with escaping appropriate to each HTML context. */ function samtyk_cmp_escape_embed_node(DOMNode $node): string { if ($node instanceof DOMText) { return esc_html($node->nodeValue); } if (!$node instanceof DOMElement) { return ''; } $tag = strtolower($node->tagName); $html = '<' . $tag; foreach ($node->attributes as $attribute) { $html .= ' ' . $attribute->name . '="' . esc_attr($attribute->value) . '"'; } $html .= '>'; if (in_array($tag, ['img', 'source', 'br'], true)) { return $html; } if ($tag === 'script') { // Executable source is intentionally preserved. Only signed, explicitly approved // snippets reach frontend rendering; HTML escaping here would corrupt JavaScript. $html .= $node->textContent; } else { foreach ($node->childNodes as $child) { $html .= samtyk_cmp_escape_embed_node($child); } } return $html . ''; } /** Emit validated nodes using WordPress' script API and late HTML-context escaping. */ function samtyk_cmp_print_embed_node(DOMNode $node): void { if ($node instanceof DOMText) { echo esc_html($node->nodeValue); return; } if (!$node instanceof DOMElement) { return; } $tag = strtolower($node->tagName); if ($tag === 'script') { $attributes = []; foreach ($node->attributes as $attribute) { $attributes[$attribute->name] = $attribute->value; } wp_print_inline_script_tag($node->textContent, $attributes); return; } echo '<' . esc_html($tag); foreach ($node->attributes as $attribute) { echo ' ' . esc_attr($attribute->name) . '="' . esc_attr($attribute->value) . '"'; } echo '>'; if (in_array($tag, ['img', 'source', 'br'], true)) { return; } foreach ($node->childNodes as $child) { samtyk_cmp_print_embed_node($child); } echo ''; } function samtyk_cmp_convert_embed_snippet(string $source, array $categories, string $identity, bool $print = false): array { if (trim($source) === '') { return samtyk_cmp_embed_conversion_error(__('Enter a script or embed code.', 'samtyk-cmp')); } if (strlen($source) > SAMTYK_CMP_SNIPPET_MAX_BYTES) { return samtyk_cmp_embed_conversion_error(__('The code is larger than the allowed 100 KB.', 'samtyk-cmp')); } if (!samtyk_cmp_valid_snippet_categories($categories)) { return samtyk_cmp_embed_conversion_error(__('Select valid consent categories.', 'samtyk-cmp')); } $categories = samtyk_cmp_normalize_snippet_categories($categories); if (strpos($source, "\0") !== false || !preg_match('//u', $source)) { return samtyk_cmp_embed_conversion_error(__('The code must contain valid UTF-8 text without null bytes.', 'samtyk-cmp')); } if (!class_exists('DOMDocument')) { return samtyk_cmp_embed_conversion_error(__('The server cannot process HTML embeds.', 'samtyk-cmp')); } $previous_errors = libxml_use_internal_errors(true); $document = new DOMDocument('1.0', 'UTF-8'); $wrapper_id = 'samtyk-cmp-parser-root'; $loaded = $document->loadHTML( '
' . $source . '
', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); libxml_clear_errors(); libxml_use_internal_errors($previous_errors); $wrapper = $document->getElementById($wrapper_id); if (!$loaded || !$wrapper instanceof DOMElement) { return samtyk_cmp_embed_conversion_error(__('The code could not be parsed as HTML.', 'samtyk-cmp')); } $allowed_tags = array_fill_keys(samtyk_cmp_get_embed_allowed_tags(), true); $elements = []; foreach ($wrapper->getElementsByTagName('*') as $element) { $elements[] = $element; } $category_value = implode(',', $categories); $normalized_identity = samtyk_cmp_normalize_embed_identity($identity, $source, $categories); $resource_index = 0; foreach ($elements as $element) { $tag_name = strtolower($element->tagName); if (!isset($allowed_tags[$tag_name])) { return samtyk_cmp_embed_conversion_error( /* translators: %s: Unsupported HTML tag name. */ sprintf(__('The HTML tag <%s> is not supported.', 'samtyk-cmp'), $tag_name) ); } $attribute_names = []; foreach ($element->attributes as $attribute) { $attribute_names[] = strtolower($attribute->name); } foreach ($attribute_names as $attribute_name) { if (!preg_match('/^[a-z][a-z0-9_.:-]*$/D', $attribute_name)) { $element->removeAttribute($attribute_name); continue; } if (strpos($attribute_name, 'data-samtyk-') === 0 || strpos($attribute_name, 'data-cookiepopup-') === 0) { return samtyk_cmp_embed_conversion_error(__('The code contains reserved consent-manager attributes.', 'samtyk-cmp')); } if (strpos($attribute_name, 'on') === 0 || !samtyk_cmp_is_allowed_embed_attribute($attribute_name, $tag_name)) { $element->removeAttribute($attribute_name); } } foreach (['href', 'src', 'poster', 'data-src', 'data-poster', 'srcset', 'data-srcset'] as $url_attribute) { if (!$element->hasAttribute($url_attribute)) { continue; } $value = $element->getAttribute($url_attribute); $clean = strpos($url_attribute, 'srcset') !== false ? samtyk_cmp_sanitize_embed_srcset($value) : samtyk_cmp_sanitize_embed_url($value, $url_attribute === 'href'); if ($clean === '') { return samtyk_cmp_embed_conversion_error(__('The code contains an unsupported or unsafe URL.', 'samtyk-cmp')); } $element->setAttribute($url_attribute, $clean); } if ($element->hasAttribute('style')) { $style = function_exists('safecss_filter_attr') ? safecss_filter_attr($element->getAttribute('style')) : ''; if ($style === '') { $element->removeAttribute('style'); } else { $element->setAttribute('style', $style); } } if ($element->hasAttribute('href')) { $href = samtyk_cmp_sanitize_embed_url($element->getAttribute('href'), true); if ($href === '') { $element->removeAttribute('href'); } else { $element->setAttribute('href', $href); } } $is_resource = in_array($tag_name, ['script', 'iframe', 'img', 'source', 'video', 'audio'], true); if (!$is_resource || $categories === []) { continue; } $resource_index++; if ($element->hasAttribute('src')) { $source_url = samtyk_cmp_sanitize_embed_url($element->getAttribute('src')); $element->removeAttribute('src'); if ($source_url !== '') { $element->setAttribute('data-src', $source_url); } } if (in_array($tag_name, ['img', 'source'], true) && $element->hasAttribute('srcset')) { $element->setAttribute('data-srcset', $element->getAttribute('srcset')); $element->removeAttribute('srcset'); } if ($tag_name === 'video' && $element->hasAttribute('poster')) { $poster = samtyk_cmp_sanitize_embed_url($element->getAttribute('poster')); $element->removeAttribute('poster'); if ($poster !== '') { $element->setAttribute('data-poster', $poster); } } if ($tag_name === 'script') { $element->setAttribute('type', 'text/plain'); } $element->setAttribute('data-cookiepopup-category', $category_value); $element->setAttribute('data-cookiepopup-id', 'samtyk-' . $normalized_identity . '-' . $resource_index); } $converted = ''; foreach ($wrapper->childNodes as $child) { $converted .= samtyk_cmp_escape_embed_node($child); } if (trim($converted) === '') { return samtyk_cmp_embed_conversion_error(__('The code does not contain supported HTML.', 'samtyk-cmp')); } $template_id = 'samtyk-' . $normalized_identity; if ($print) { if ($categories !== []) { echo ''; } } return [ 'success' => true, 'html' => $converted, 'managed_html' => $categories === [] ? $converted : '', 'error' => '', ]; } function samtyk_cmp_register_snippet_post_type(): void { register_post_type(SAMTYK_CMP_SNIPPET_POST_TYPE, [ 'labels' => [ 'name' => __('Scripts and embeds', 'samtyk-cmp'), 'singular_name' => __('Script or embed', 'samtyk-cmp'), ], 'public' => false, 'publicly_queryable' => false, 'show_ui' => false, 'show_in_menu' => false, 'show_in_rest' => false, 'exclude_from_search' => true, 'rewrite' => false, 'query_var' => false, 'supports' => ['title', 'editor'], // All writes use our nonce-protected handlers, never the default post editor/XML-RPC. 'map_meta_cap' => false, 'capabilities' => array_merge( array_fill_keys(['edit_post', 'edit_posts', 'edit_others_posts', 'edit_published_posts', 'edit_private_posts', 'publish_posts', 'create_posts', 'delete_post', 'delete_posts', 'delete_others_posts', 'delete_published_posts', 'delete_private_posts'], 'do_not_allow'), ['read_post' => 'manage_options', 'read_private_posts' => 'manage_options'] ), ]); } function samtyk_cmp_get_valid_public_content_ids($content_ids): array { if (!is_array($content_ids)) { return []; } $valid_ids = []; foreach ($content_ids as $content_id) { $content_id = (int) $content_id; if ($content_id <= 0 || isset($valid_ids[$content_id])) { continue; } $post_type = get_post_type($content_id); $post_type_object = $post_type !== '' ? get_post_type_object($post_type) : null; if ( $post_type === 'attachment' || !$post_type_object || empty($post_type_object->public) || get_post_status($content_id) !== 'publish' ) { continue; } $valid_ids[$content_id] = $content_id; } return array_values($valid_ids); } function samtyk_cmp_get_snippet(int $post_id): ?array { $post = get_post($post_id); if (!$post || $post->post_type !== SAMTYK_CMP_SNIPPET_POST_TYPE) { return null; } $categories = samtyk_cmp_normalize_snippet_categories(get_post_meta($post_id, '_samtyk_categories', true)); $location = (string) get_post_meta($post_id, '_samtyk_location', true); $visibility = (string) get_post_meta($post_id, '_samtyk_visibility', true); $snippet = [ 'id' => (int) $post->ID, 'name' => (string) $post->post_title, 'source' => (string) $post->post_content, 'generated_code' => '', 'categories' => $categories, 'location' => in_array($location, ['head', 'body_open', 'footer', 'shortcode'], true) ? $location : 'head', 'shortcode_id' => (string) get_post_meta($post_id, '_samtyk_shortcode_id', true), 'placeholder_enabled' => (bool) get_post_meta($post_id, '_samtyk_placeholder_enabled', true), 'placeholder_text' => (string) get_post_meta($post_id, '_samtyk_placeholder_text', true), 'placeholder_icon' => (string) get_post_meta($post_id, '_samtyk_placeholder_icon', true), 'active' => $post->post_status === 'publish', 'visibility' => $visibility === 'selected' ? 'selected' : 'all', 'content_ids' => samtyk_cmp_get_valid_public_content_ids(get_post_meta($post_id, '_samtyk_content_ids', true)), 'modified' => isset($post->post_modified) ? (string) $post->post_modified : '', ]; $approval = (string) get_post_meta($post_id, '_samtyk_code_approval', true); $snippet['approved'] = $approval !== '' && hash_equals(samtyk_cmp_snippet_approval($snippet), $approval); if ($snippet['approved'] && samtyk_cmp_valid_snippet_categories(get_post_meta($post_id, '_samtyk_categories', true))) { $conversion = samtyk_cmp_convert_embed_snippet($snippet['source'], $categories, ''); if ($conversion['success']) { $snippet['generated_code'] = $conversion['managed_html']; } } return $snippet; } /** Bind approval to the site secret, post, source and execution/placement settings. */ function samtyk_cmp_snippet_approval(array $snippet): string { return wp_hash(wp_json_encode([ SAMTYK_CMP_SNIPPET_POLICY_VERSION, get_current_blog_id(), $snippet['id'], $snippet['source'], $snippet['categories'], $snippet['location'], $snippet['shortcode_id'], $snippet['visibility'], // Approval tracks configured targets, independent of later publication changes. get_post_meta($snippet['id'], '_samtyk_content_ids', true), ]), 'auth'); } /** Late validation and context-aware escaping for both shortcode and automatic output. */ function samtyk_cmp_escape_snippet_output(int $post_id): string { ob_start(); samtyk_cmp_print_snippet_output($post_id); return (string) ob_get_clean(); } function samtyk_cmp_print_snippet_output(int $post_id): void { $snippet = samtyk_cmp_get_snippet($post_id); if ($snippet && $snippet['active'] && $snippet['generated_code'] !== '') { samtyk_cmp_convert_embed_snippet($snippet['source'], $snippet['categories'], '', true); } } function samtyk_cmp_invalidate_shortcode_index(): void { unset($GLOBALS['samtyk_cmp_shortcode_index']); } function samtyk_cmp_invalidate_shortcode_meta_index($meta_id, $post_id, $meta_key): void { if ($meta_key === '_samtyk_shortcode_id') { samtyk_cmp_invalidate_shortcode_index(); } } function samtyk_cmp_find_shortcode_post_id(string $shortcode_id): int { // Request-local only: fetch and prime metadata once instead of querying postmeta for each shortcode. if (!isset($GLOBALS['samtyk_cmp_shortcode_index'])) { $index = []; $post_ids = get_posts([ 'post_type' => SAMTYK_CMP_SNIPPET_POST_TYPE, 'post_status' => ['publish', 'draft'], 'posts_per_page' => -1, 'fields' => 'ids', 'orderby' => 'ID', 'order' => 'ASC', 'no_found_rows' => true, ]); update_meta_cache('post', $post_ids); foreach ($post_ids as $post_id) { $id = (string) get_post_meta((int) $post_id, '_samtyk_shortcode_id', true); if ($id !== '' && !isset($index[$id])) { $index[$id] = (int) $post_id; } } $GLOBALS['samtyk_cmp_shortcode_index'] = $index; } return $GLOBALS['samtyk_cmp_shortcode_index'][$shortcode_id] ?? 0; } function samtyk_cmp_save_snippet(array $input, int $post_id = 0): array { if (!samtyk_cmp_can_manage_snippet_code()) { return ['success' => false, 'post_id' => 0, 'error' => __('Managing executable code requires the unfiltered_html capability.', 'samtyk-cmp')]; } if (!empty($input['source_error'])) { return ['success' => false, 'post_id' => 0, 'error' => $input['source_error']]; } if (!samtyk_cmp_valid_snippet_categories($input['categories'] ?? [])) { return ['success' => false, 'post_id' => 0, 'error' => __('Select valid consent categories.', 'samtyk-cmp')]; } $name = isset($input['name']) ? trim(sanitize_text_field($input['name'])) : ''; $source = isset($input['source']) && is_string($input['source']) ? $input['source'] : ''; $categories = samtyk_cmp_normalize_snippet_categories($input['categories'] ?? []); $location = isset($input['location']) && in_array($input['location'], ['head', 'body_open', 'footer', 'shortcode'], true) ? $input['location'] : ''; $visibility = ($input['visibility'] ?? 'all') === 'selected' ? 'selected' : 'all'; $content_ids = samtyk_cmp_get_valid_public_content_ids($input['content_ids'] ?? []); $shortcode_id = $post_id > 0 ? (string) get_post_meta($post_id, '_samtyk_shortcode_id', true) : ''; if ($shortcode_id === '') { $shortcode_id = isset($input['shortcode_id']) && is_string($input['shortcode_id']) ? $input['shortcode_id'] : ''; if (!preg_match('/^[a-f0-9]{32}$/D', $shortcode_id)) { $shortcode_id = bin2hex(random_bytes(16)); } if (samtyk_cmp_find_shortcode_post_id($shortcode_id) > 0) { return ['success' => false, 'post_id' => 0, 'error' => __('This shortcode ID is already in use. Open a new form and try again.', 'samtyk-cmp')]; } } if ($name === '') { return ['success' => false, 'post_id' => 0, 'error' => __('Enter a name.', 'samtyk-cmp')]; } if ($location === '') { return ['success' => false, 'post_id' => 0, 'error' => __('Select a valid placement.', 'samtyk-cmp')]; } if ($location !== 'shortcode' && $visibility === 'selected' && $content_ids === []) { return ['success' => false, 'post_id' => 0, 'error' => __('Select at least one public page or item.', 'samtyk-cmp')]; } $initial_conversion = samtyk_cmp_convert_embed_snippet($source, $categories, ''); if (!$initial_conversion['success']) { return ['success' => false, 'post_id' => 0, 'error' => $initial_conversion['error']]; } $post_data = [ 'post_type' => SAMTYK_CMP_SNIPPET_POST_TYPE, 'post_status' => !empty($input['active']) ? 'publish' : 'draft', 'post_title' => $name, 'post_content' => function_exists('wp_slash') ? wp_slash($source) : $source, ]; if ($post_id > 0) { $existing = get_post($post_id); if (!$existing || $existing->post_type !== SAMTYK_CMP_SNIPPET_POST_TYPE) { return ['success' => false, 'post_id' => 0, 'error' => __('The script or embed could not be found.', 'samtyk-cmp')]; } // Revoke approval before changing source or any execution settings. update_post_meta($post_id, '_samtyk_code_approval', ''); $post_data['ID'] = $post_id; $saved_post_id = wp_update_post($post_data, true); } else { $saved_post_id = wp_insert_post($post_data, true); } if (is_wp_error($saved_post_id) || (int) $saved_post_id <= 0) { return ['success' => false, 'post_id' => 0, 'error' => __('The script or embed could not be saved.', 'samtyk-cmp')]; } $saved_post_id = (int) $saved_post_id; // Do not approve a different value after WordPress filters or storage transformations. if ((string) get_post($saved_post_id)->post_content !== $source) { return ['success' => false, 'post_id' => 0, 'error' => __('WordPress changed the code while saving. Review it and save again.', 'samtyk-cmp')]; } // Retained only for compatibility; frontend always regenerates from approved source. update_post_meta($saved_post_id, '_samtyk_generated_code', wp_slash($initial_conversion['managed_html'])); update_post_meta($saved_post_id, '_samtyk_categories', $categories); update_post_meta($saved_post_id, '_samtyk_location', $location); update_post_meta($saved_post_id, '_samtyk_visibility', $visibility); update_post_meta($saved_post_id, '_samtyk_content_ids', $content_ids); update_post_meta($saved_post_id, '_samtyk_shortcode_id', $shortcode_id); update_post_meta($saved_post_id, '_samtyk_placeholder_enabled', $categories !== [] && !empty($input['placeholder_enabled'])); $placeholder_text = isset($input['placeholder_text']) && is_string($input['placeholder_text']) ? sanitize_textarea_field($input['placeholder_text']) : ''; if (!empty($input['placeholder_default']) || samtyk_cmp_is_default_placeholder_text($placeholder_text)) { $placeholder_text = ''; } update_post_meta($saved_post_id, '_samtyk_placeholder_text', wp_slash($placeholder_text)); $placeholder_icon = isset($input['placeholder_icon']) && in_array($input['placeholder_icon'], ['samtyk', 'lock', 'shield', 'video'], true) ? $input['placeholder_icon'] : ''; update_post_meta($saved_post_id, '_samtyk_placeholder_icon', $placeholder_icon); $saved = samtyk_cmp_get_snippet($saved_post_id); if (!$saved || $saved['categories'] !== $categories || $saved['location'] !== $location || $saved['visibility'] !== $visibility || $saved['content_ids'] !== $content_ids || $saved['shortcode_id'] !== $shortcode_id) { return ['success' => false, 'post_id' => 0, 'error' => __('The script or embed could not be saved.', 'samtyk-cmp')]; } update_post_meta($saved_post_id, '_samtyk_code_approval', samtyk_cmp_snippet_approval($saved)); return ['success' => true, 'post_id' => $saved_post_id, 'error' => '']; } function samtyk_cmp_snippet_matches_request(array $snippet): bool { if (($snippet['location'] ?? '') === 'shortcode') { return true; } if (($snippet['visibility'] ?? 'all') !== 'selected') { return true; } if (!is_singular()) { return false; } $queried_id = (int) get_queried_object_id(); return $queried_id > 0 && in_array($queried_id, samtyk_cmp_get_valid_public_content_ids($snippet['content_ids'] ?? []), true); } function samtyk_cmp_get_placeholder_icon(string $icon): string { if ($icon === 'samtyk') { return ''; } $paths = [ 'lock' => '', 'shield' => '', 'video' => '', ]; if (!isset($paths[$icon])) { return ''; } return wp_kses('', [ 'svg' => array_fill_keys(['class', 'viewbox', 'fill', 'stroke', 'stroke-width', 'stroke-linecap', 'stroke-linejoin', 'aria-hidden', 'focusable'], true), 'path' => ['d' => true], 'rect' => array_fill_keys(['x', 'y', 'width', 'height', 'rx'], true), ]); } function samtyk_cmp_render_embed_shortcode($attributes = []): string { $settings = samtyk_cmp_get_settings(); $id = is_array($attributes) && isset($attributes['id']) && is_string($attributes['id']) ? $attributes['id'] : ''; if (empty($settings['enabled']) || !preg_match('/^[a-f0-9]{32}$/D', $id)) { return ''; } $post_id = samtyk_cmp_find_shortcode_post_id($id); if ($post_id === 0) { return ''; } $snippet = samtyk_cmp_get_snippet($post_id); if (!$snippet || !$snippet['active'] || $snippet['location'] !== 'shortcode' || $snippet['generated_code'] === '') { return ''; } if (!$snippet['placeholder_enabled'] || $snippet['categories'] === []) { return samtyk_cmp_escape_snippet_output($post_id); } $text = samtyk_cmp_is_default_placeholder_text($snippet['placeholder_text']) ? samtyk_cmp_get_placeholder_default_text($snippet['categories']) : $snippet['placeholder_text']; return '
' . samtyk_cmp_get_placeholder_icon($snippet['placeholder_icon']) . '

' . esc_html($text) . '

' . '' . '
' . samtyk_cmp_escape_snippet_output($post_id) . '
'; } function samtyk_cmp_render_managed_snippets(string $location): void { if (!in_array($location, ['head', 'body_open', 'footer'], true)) { return; } $settings = samtyk_cmp_get_settings(); if (empty($settings['enabled'])) { return; } $posts = get_posts([ 'post_type' => SAMTYK_CMP_SNIPPET_POST_TYPE, 'post_status' => 'publish', 'posts_per_page' => -1, 'orderby' => ['menu_order' => 'ASC', 'ID' => 'ASC'], 'no_found_rows' => true, ]); foreach ($posts as $post) { $snippet = samtyk_cmp_get_snippet((int) $post->ID); if ( !$snippet || $snippet['location'] !== $location || !samtyk_cmp_snippet_matches_request($snippet) ) { continue; } samtyk_cmp_print_snippet_output((int) $post->ID); } } function samtyk_cmp_has_applicable_managed_snippets(): bool { $posts = get_posts([ 'post_type' => SAMTYK_CMP_SNIPPET_POST_TYPE, 'post_status' => 'publish', 'posts_per_page' => -1, 'no_found_rows' => true, ]); foreach ($posts as $post) { $snippet = samtyk_cmp_get_snippet((int) $post->ID); if ($snippet && $snippet['generated_code'] !== '' && samtyk_cmp_snippet_matches_request($snippet)) { return true; } } return false; } function samtyk_cmp_enqueue_script_embed_manager(): void { $settings = samtyk_cmp_get_settings(); if (empty($settings['enabled']) || !samtyk_cmp_has_applicable_managed_snippets()) { return; } wp_enqueue_script( 'samtyk-cmp-script-embed-manager', SAMTYK_CMP_PLUGIN_URL . 'assets/script-embed-manager.js', [], SAMTYK_CMP_VERSION, false ); samtyk_cmp_enqueue_placeholder_styles(); } add_action('init', 'samtyk_cmp_register_snippet_post_type'); add_action('save_post_' . SAMTYK_CMP_SNIPPET_POST_TYPE, 'samtyk_cmp_invalidate_shortcode_index'); add_action('before_delete_post', 'samtyk_cmp_invalidate_shortcode_index'); add_action('added_post_meta', 'samtyk_cmp_invalidate_shortcode_meta_index', 10, 3); add_action('updated_post_meta', 'samtyk_cmp_invalidate_shortcode_meta_index', 10, 3); add_action('deleted_post_meta', 'samtyk_cmp_invalidate_shortcode_meta_index', 10, 3); add_shortcode('samtyk_embed', 'samtyk_cmp_render_embed_shortcode'); add_action('wp_enqueue_scripts', 'samtyk_cmp_enqueue_script_embed_manager'); add_action('wp_head', static function (): void { samtyk_cmp_render_managed_snippets('head'); }, 20); add_action('wp_body_open', static function (): void { samtyk_cmp_render_managed_snippets('body_open'); }, 20); add_action('wp_footer', static function (): void { samtyk_cmp_render_managed_snippets('footer'); }, 20);