[/content_blocker]
*/
public static function shortcode( array $atts, ?string $content = null ): string {
$atts = shortcode_atts( [ 'id' => '' ], $atts, 'content_blocker' );
$id = sanitize_key( $atts['id'] );
if ( $id === '' ) {
return '';
}
$svc = CB_Settings::get_service( $id );
if ( $svc === null ) {
return '';
}
// Disabled blocker → let the embedded content load normally (no blocking).
if ( ! ( $svc['enabled'] ?? true ) ) {
return $content ?? '';
}
// Extract src + dimensions from the inner iframe
$src = '';
$dims = [];
if ( $content !== null && $content !== '' ) {
$attrs = self::extract_iframe_attrs( $content );
$src = $attrs['src'];
$dims = [ 'width' => $attrs['width'], 'height' => $attrs['height'] ];
}
return self::render_placeholder( $svc, $src, $dims );
}
/**
* Shortcode: [content_blocker_revoke]
* Renders, by default, a visible text link (not a button) so it doesn't get
* confused with a cookie banner's revoke control. Attributes:
* text="…" custom link label
* style="link|button" default "link"
* note="yes|no" show the clarifying hint (default "yes")
*/
public static function revoke_shortcode( array|string $atts = [] ): string {
$atts = shortcode_atts( [
'text' => __( 'Einwilligung für externe Inhalte widerrufen', 'gdpr-content-blocker' ),
'style' => 'link',
'note' => 'yes',
], $atts, 'content_blocker_revoke' );
$class = $atts['style'] === 'button' ? 'cb-revoke-btn' : 'cb-revoke-link';
$out = ''
. esc_html( $atts['text'] )
. '';
if ( $atts['note'] === 'yes' ) {
$out .= ''
. esc_html__( 'Betrifft nur die Freigabe externer Einbettungen (z. B. Karten, Videos). Cookie-Einstellungen werden separat verwaltet.', 'gdpr-content-blocker' )
. '';
}
return $out;
}
/**
* Shortcode: [content_blocker_services]
* Lists every configured third-party service with the Art. 13 details
* (provider, recipient, third-country note, purpose, privacy link).
* Meant for embedding in the privacy policy.
*/
public static function services_shortcode(): string {
$services = CB_Settings::get_services();
if ( empty( $services ) ) {
return '';
}
$out = '
';
foreach ( $services as $svc ) {
// Only list active blockers — disabled ones aren't being managed.
if ( ! ( $svc['enabled'] ?? true ) ) {
continue;
}
$name = esc_html( $svc['name'] ?? '' );
if ( $name === '' ) {
continue;
}
$out .= '- ';
$out .= '' . $name . '';
$out .= '
';
if ( ! empty( $svc['recipient'] ) ) {
$recipient = esc_html( $svc['recipient'] );
if ( ! empty( $svc['third_country'] ) ) {
$recipient .= ' (' . esc_html__( 'Übermittlung in ein Drittland außerhalb der EU/des EWR', 'gdpr-content-blocker' ) . ')';
}
$out .= '- ' . esc_html__( 'Empfänger', 'gdpr-content-blocker' ) . '
- ' . $recipient . '
';
}
if ( ! empty( $svc['purpose'] ) ) {
$out .= '- ' . esc_html__( 'Zweck', 'gdpr-content-blocker' ) . '
- ' . esc_html( $svc['purpose'] ) . '
';
}
$out .= '- ' . esc_html__( 'Setzt Cookies', 'gdpr-content-blocker' ) . '
- '
. ( ! empty( $svc['sets_cookie'] ) ? esc_html__( 'Ja', 'gdpr-content-blocker' ) : esc_html__( 'Nein', 'gdpr-content-blocker' ) )
. '
';
if ( ! empty( $svc['privacy_url'] ) ) {
$url = esc_url( $svc['privacy_url'] );
$out .= '- ' . esc_html__( 'Datenschutz', 'gdpr-content-blocker' ) . '
'
. '- ' . $url . '
';
}
$out .= '
';
}
$out .= '
';
return $out;
}
/**
* Build the placeholder HTML for a given service.
* $src is the real iframe URL (empty string if unknown).
* $dims may contain 'width' and 'height' (numbers or e.g. "100%") taken
* from the original iframe so the placeholder reserves the same height.
*/
public static function render_placeholder( array $svc, string $src = '', array $dims = [] ): string {
$id = esc_attr( $svc['id'] );
$name = esc_html( $svc['name'] );
$recipient = esc_html( $svc['recipient'] );
$purpose = esc_html( $svc['purpose'] );
$privacy_url = esc_url( $svc['privacy_url'] ?? '' );
$third = ! empty( $svc['third_country'] );
$custom_text = $svc['placeholder_text'] ?? '';
if ( $custom_text !== '' ) {
$info_text = esc_html( $custom_text );
} else {
$info_text = sprintf(
/* translators: %s: provider name */
esc_html__( 'Um diesen Inhalt von %s zu laden, ist Ihre Einwilligung erforderlich. Dabei werden personenbezogene Daten (z. B. Ihre IP-Adresse) an den Anbieter übertragen.', 'gdpr-content-blocker' ),
'' . $name . ''
);
}
$third_note = '';
if ( $third ) {
$third_note = ''
. esc_html__( '⚠ Datenübermittlung in ein Drittland außerhalb der EU/des EWR', 'gdpr-content-blocker' )
. '';
}
$privacy_link = '';
if ( $privacy_url !== '' ) {
$privacy_link = ''
. esc_html__( 'Datenschutzerklärung des Anbieters', 'gdpr-content-blocker' )
. '';
}
$data_src = $src !== '' ? ' data-src="' . esc_attr( $src ) . '"' : '';
// Reserve the embed's height so the layout doesn't jump, and remember the
// original dimensions for the iframe that gets created on consent.
$width = isset( $dims['width'] ) ? (string) $dims['width'] : '';
$height = isset( $dims['height'] ) ? (string) $dims['height'] : '';
$style_at = '';
if ( $height !== '' && ctype_digit( $height ) ) {
$style_at = ' style="min-height:' . esc_attr( $height ) . 'px"';
}
$data_dims = '';
if ( $width !== '' ) {
$data_dims .= ' data-width="' . esc_attr( $width ) . '"';
}
if ( $height !== '' ) {
$data_dims .= ' data-height="' . esc_attr( $height ) . '"';
}
return ''
. '
'
. '
' . $info_text . '
'
. '
'
. '' . esc_html__( 'Empfänger:', 'gdpr-content-blocker' ) . ' '
. $recipient
. ( $third_note !== '' ? ' — ' . $third_note : '' )
. '
'
. '
'
. '' . esc_html__( 'Zweck:', 'gdpr-content-blocker' ) . ' '
. $purpose
. '
'
. ( $privacy_link !== '' ? '
' . $privacy_link . '
' : '' )
. '
'
. '
'
. '
';
}
/** Pull the src attribute out of an iframe string. */
public static function extract_iframe_src( string $html ): string {
return self::extract_iframe_attrs( $html )['src'];
}
/**
* Pull src + width + height out of an iframe string.
* Height is also read from an inline style="height:NNNpx" if no attribute.
* Returns [ 'src' => string, 'width' => string, 'height' => string ].
*/
public static function extract_iframe_attrs( string $html ): array {
$src = '';
if ( preg_match( '/\bsrc=["\']([^"\']+)["\']/i', $html, $m ) ) {
$src = esc_url_raw( $m[1] );
}
$width = '';
if ( preg_match( '/\bwidth=["\']?(\d+(?:%|px)?)["\']?/i', $html, $m ) ) {
$width = $m[1];
}
$height = '';
if ( preg_match( '/\bheight=["\']?(\d+(?:%|px)?)["\']?/i', $html, $m ) ) {
$height = $m[1];
} elseif ( preg_match( '/height\s*:\s*(\d+)px/i', $html, $m ) ) {
$height = $m[1];
}
// Normalise "450px" → "450" so it can be used as a numeric attribute.
$width = preg_replace( '/px$/', '', $width );
$height = preg_replace( '/px$/', '', $height );
return [ 'src' => $src, 'width' => $width, 'height' => $height ];
}
}