*/ public static function requirements(): array { return array( 'a' => array( 'label' => __( 'La política adoptada, con su fecha y versión', 'cumpleconsent' ), 'patterns' => array( '/versi[óo]n\s*[:\-]?\s*[\d\.]+/iu', '/fecha[^.]{0,40}(?:versi[óo]n|actualizaci[óo]n)|[úu]ltima\s+(?:actualizaci[óo]n|versi[óo]n)/iu' ), 'needs' => __( 'número de versión y fecha', 'cumpleconsent' ), ), 'b' => array( 'label' => __( 'Identificación del responsable, su representante legal y el encargado de prevención (si existe)', 'cumpleconsent' ), 'patterns' => array( '/responsable\s+del\s+(?:tratamiento|banco)/iu', '/representante\s+legal/iu', '/encargado\s+de\s+prevenci[óo]n|delegado/iu' ), 'needs' => __( 'nombre o razón social del responsable (y del representante legal si corresponde)', 'cumpleconsent' ), ), 'c' => array( 'label' => __( 'Domicilio, correo electrónico o formulario para notificarte', 'cumpleconsent' ), 'patterns' => array( '/@/u', '/formulario\s+de\s+contacto|domicilio\s+postal|direcci[óo]n\s+postal/iu' ), 'needs' => __( 'un correo o dirección de contacto', 'cumpleconsent' ), ), 'd' => array( 'label' => __( 'Categorías de datos, universo de titulares, destinatarios, finalidades y base de licitud', 'cumpleconsent' ), 'patterns' => array( '/(?:qu[ée]\s+datos|categor[íi]as\s+de\s+datos|datos\s+que\s+tratamos)/iu', '/(?:finalidades|para\s+qu[ée])/iu', '/(?:destinatarios|terceros|encargados)/iu', '/(?:base\s+de\s+licitud|base\s+legal|fundamento)/iu' ), 'needs' => __( 'datos, finalidades, destinatarios y base de licitud', 'cumpleconsent' ), ), 'e' => array( 'label' => __( 'Política y medidas de seguridad adoptadas', 'cumpleconsent' ), 'patterns' => array( '/(?:medidas\s+de\s+seguridad|seguridad\s+de\s+la\s+informaci[óo]n)/iu', '/(?:cifrado|seudonimizaci[óo]n|control\s+de\s+acceso|respaldo)/iu' ), 'needs' => __( 'mención de medidas de seguridad concretas', 'cumpleconsent' ), ), 'f' => array( 'label' => __( 'Derechos de acceso, rectificación, supresión, oposición y portabilidad', 'cumpleconsent' ), 'patterns' => array( '/acceso/iu', '/rectificaci[óo]n/iu', '/supresi[óo]n|cancelaci[óo]n/iu', '/oposici[óo]n/iu', '/portabilidad/iu' ), 'needs' => __( 'los derechos y la forma de ejercerlos', 'cumpleconsent' ), ), 'g' => array( 'label' => __( 'Derecho a reclamar ante la Agencia de Protección de Datos Personales', 'cumpleconsent' ), 'patterns' => array( '/(?:Agencia\s+de\s+Protecci[óo]n\s+de\s+Datos|Agencia)/u', '/(?:reclam|reclamaci[óo]n)/iu' ), 'needs' => __( 'mención de la Agencia y del reclamo', 'cumpleconsent' ), ), 'h' => array( 'label' => __( 'Transferencias internacionales y su nivel de protección o garantías', 'cumpleconsent' ), 'patterns' => array( '/(?:transferencia|transferencias)/iu', '/(?:tercer\s+pa[íi]s|fuera\s+de\s+Chile|internacional)/iu' ), 'needs' => __( 'si hay o no transferencias y con qué garantías', 'cumpleconsent' ), ), 'i' => array( 'label' => __( 'Periodo de conservación de los datos', 'cumpleconsent' ), 'patterns' => array( '/(?:conserv|retenci[óo]n|plazo)/iu', '/mes(?:es)?|a[ñn]os?|d[íi]as?/iu' ), 'needs' => __( 'un plazo concreto (meses o años)', 'cumpleconsent' ), ), 'j' => array( 'label' => __( 'Fuente de los datos y si provienen de fuentes de acceso público', 'cumpleconsent' ), 'patterns' => array( '/(?:origen\s+de\s+los\s+datos|fuente\s+de\s+(?:los\s+)?datos|de\s+d[óo]nde)/iu', '/(?:fuentes\s+de\s+acceso\s+p[úu]blico|datos\s+del\s+propio\s+titular)/iu' ), 'needs' => __( 'indicación del origen de los datos', 'cumpleconsent' ), ), 'k' => array( 'label' => __( 'Derecho a retirar el consentimiento en cualquier momento', 'cumpleconsent' ), 'patterns' => array( '/(?:retirar|revocar)\s+(?:tu\s+|el\s+)?consentimiento/iu', '/(?:en\s+cualquier\s+momento|cuando\s+quieras)/iu' ), 'needs' => __( 'el derecho a retirar el consentimiento', 'cumpleconsent' ), ), 'l' => array( 'label' => __( 'Decisiones automatizadas y elaboración de perfiles', 'cumpleconsent' ), 'patterns' => array( '/(?:decisiones\s+automatizadas|perfiles|elaboraci[óo]n\s+de\s+perfiles)/iu', '/(?:no\s+(?:adoptamos|\w+)\s+decisiones\s+automatizadas|no\s+realizamos\s+decisiones)/iu' ), 'needs' => __( 'declaración sobre decisiones automatizadas (aunque sea para decir que no las hay)', 'cumpleconsent' ), ), ); } /** * Versión vigente del aviso/política. * * @return string */ public static function version(): string { if ( null !== self::$version_cache ) { return self::$version_cache; } $manual = (string) Settings::get( 'policy_version', '1.0' ); if ( '' === trim( $manual ) ) { $manual = '1.0'; } if ( Settings::get( 'policy_auto_version', false ) ) { $page_id = (int) Settings::get( 'policy_page_id', 0 ); $post = $page_id ? get_post( $page_id ) : null; if ( $post ) { $stamp = substr( md5( (string) $post->post_content . '|' . (string) $post->post_modified_gmt ), 0, 8 ); self::$version_cache = $manual . '+' . $stamp; return self::$version_cache; } } self::$version_cache = $manual; return self::$version_cache; } /** Invalida lo calculado (se llama al guardar ajustes). */ public static function flush_version(): void { self::$version_cache = null; self::$linked_cache = null; } /** * Página que hace de política en este sitio: la asignada, la del nombre habitual * ya publicada, o la que WordPress tiene marcada como política de privacidad. * * Sin esta búsqueda, un sitio con su política publicada en /politica-de-privacidad/ * aparecía como “no hay política publicada” solo porque nadie la había asignado. * * @return int */ /** Direcciones habituales de la política, en orden de preferencia. */ private static function policy_slugs(): array { return array( 'politica-de-privacidad', 'politica-privacidad', 'privacidad', 'aviso-de-privacidad', 'privacy-policy' ); } public static function linked_page_id(): int { if ( null !== self::$linked_cache ) { return self::$linked_cache; } $page_id = (int) Settings::get( 'policy_page_id', 0 ); if ( $page_id && get_post( $page_id ) && self::looks_like_policy( $page_id ) ) { self::$linked_cache = $page_id; return $page_id; } foreach ( self::policy_slugs() as $slug ) { $page = get_page_by_path( $slug ); if ( $page instanceof \WP_Post && 'publish' === (string) $page->post_status && self::looks_like_policy( (int) $page->ID ) ) { self::$linked_cache = (int) $page->ID; return self::$linked_cache; } } // Por el título, como último recurso: “privacidad” en el nombre y que no sea // la política de cookies, que es otro documento y cumple otra cosa. foreach ( (array) get_posts( array( 'post_type' => 'page', 'post_status' => 'publish', 'numberposts' => 20 ) ) as $page ) { $titulo = (string) ( $page->post_title ?? '' ); if ( '' === $titulo || false === stripos( $titulo, 'privacidad' ) || false !== stripos( $titulo, 'cookie' ) ) { continue; } $id = (int) ( $page->ID ?? 0 ); if ( $id > 0 && self::looks_like_policy( $id ) ) { self::$linked_cache = $id; return $id; } } self::$linked_cache = 0; return 0; } /** * ¿La página tiene una política dentro, o es un cartel vacío? * * Sin esta comprobación, un sitio con la página “Privacidad” en construcción * quedaba enlazado a un texto inexistente y el verificador informaba 0 de 12. * * @param int $page_id Página. * @return bool */ private static function looks_like_policy( int $page_id ): bool { $texto = self::page_text( $page_id ); if ( strlen( $texto ) < 600 ) { return false; } return false !== stripos( $texto, 'privacidad' ) || false !== stripos( $texto, 'datos personales' ); } /** * Texto de una página de política, aunque su maquetador no lo guarde en post_content. * * @param int $page_id Página. * @return string */ private static function page_text( int $page_id ): string { $post = $page_id ? get_post( $page_id ) : null; if ( ! $post ) { return ''; } $texto = self::plain_text( (string) $post->post_content ); if ( strlen( $texto ) >= 600 ) { return $texto; } // Elementor y otros maquetadores guardan el contenido en metadatos: sin esto, // una política perfecta puntúa 0 porque post_content viene vacío. $datos = get_post_meta( $page_id, '_elementor_data', true ); if ( is_string( $datos ) && '' !== $datos ) { $extra = self::plain_text( $datos ); if ( strlen( $extra ) > strlen( $texto ) ) { $texto = $extra; } } if ( strlen( $texto ) >= 600 ) { return $texto; } // Último recurso: pedirle al propio sitio la página ya renderizada. Es la // misma llamada de retorno local que hace el diagnóstico, y solo se paga // cuando el contenido no está en la entrada. $url = get_permalink( $page_id ); if ( is_string( $url ) && '' !== $url ) { $resp = wp_remote_get( $url, array( 'timeout' => 8, 'redirection' => 2 ) ); if ( ! is_wp_error( $resp ) && 200 === (int) wp_remote_retrieve_response_code( $resp ) ) { $extra = self::plain_text( (string) wp_remote_retrieve_body( $resp ) ); if ( strlen( $extra ) > strlen( $texto ) ) { $texto = $extra; } } } return $texto; } /** URL de la política: la del sitio, o la que WordPress tenga marcada. */ public static function url(): string { $page_id = self::linked_page_id(); if ( $page_id ) { $url = get_permalink( $page_id ); if ( is_string( $url ) && '' !== $url ) { return $url; } } $wp_privacy = get_privacy_policy_url(); return is_string( $wp_privacy ) ? $wp_privacy : ''; } /** Enlace HTML a la política (texto escapado). */ public static function link_html( string $text ): string { $url = self::url(); if ( '' === $url ) { return esc_html( $text ); } return '' . esc_html( $text ) . ''; } // ── Generador ──────────────────────────────────────────────────────────── /** * Texto plano de la política generada (HTML de bloques simples). * * @return string */ public static function generated_text(): string { $s = Settings::all(); $owner = trim( (string) $s['owner_name'] ); $email = Rights::channel_email(); $address = (string) $s['owner_address']; $phone = (string) $s['owner_phone']; $today = date_i18n( 'j \d\e F \d\e Y' ); $months = max( 1, (int) $s['log_retention_months'] ); $purposes = Purposes::active(); $transfers = Transfers::rows(); $ops = Rat::operations(); $h = array(); $h[] = '
' . sprintf( /* translators: 1: versión, 2: fecha */ esc_html__( 'Versión %1$s · Fecha de la última versión de esta política: %2$s', 'cumpleconsent' ), esc_html( self::version() ), esc_html( $today ) ) . '
'; // 1. Responsable (14 ter b) y c)). $h[] = '' . $txt . '
'; $h[] = '' . sprintf( /* translators: 1: representante legal, 2: encargado de prevención */ esc_html__( 'Representante legal: %1$s. Encargado de prevención de datos personales: %2$s.', 'cumpleconsent' ), esc_html( '' !== trim( (string) $s['owner_rep'] ) ? (string) $s['owner_rep'] : __( 'no informado', 'cumpleconsent' ) ), esc_html( '' !== trim( (string) $s['dpo_name'] ) ? (string) $s['dpo_name'] : __( 'no designado a la fecha', 'cumpleconsent' ) ) ) . '
'; $form_url = (int) $s['rights_page_id'] ? get_permalink( (int) $s['rights_page_id'] ) : ''; $h[] = '' . sprintf( /* translators: 1: domicilio, 2: correo, 3: formulario o página de contacto, 4: teléfono */ esc_html__( 'Domicilio postal: %1$s. Correo electrónico para notificarnos solicitudes: %2$s. Formulario de contacto para ejercer tus derechos: %3$s. Teléfono: %4$s.', 'cumpleconsent' ), esc_html( $address ? $address : '[' . __( 'completa el domicilio postal', 'cumpleconsent' ) . ']' ), $email ? '' . esc_html( $email ) . '' : '[' . esc_html__( 'completa el correo de contacto', 'cumpleconsent' ) . ']', '' !== (string) $form_url ? '' . esc_html( (string) $form_url ) . '' : '' . esc_html__( 'página de contacto del sitio', 'cumpleconsent' ) . '', esc_html( $phone ? $phone : __( 'no informado', 'cumpleconsent' ) ) ) . '
'; $general = (string) $s['owner_email']; if ( '' !== $general && is_email( $general ) && $general !== $email ) { $h[] = '' . sprintf( /* translators: %s: correo de contacto general del responsable. */ esc_html__( 'Para consultas que no digan relación con tus datos personales, nuestro correo de contacto general es %s.', 'cumpleconsent' ), '' . esc_html( $general ) . '' ) . '
'; } // 2. Datos, finalidades, base de licitud y titulares (14 ter d)). $h[] = '' . esc_html__( 'A través de este sitio web tratamos los datos que nos entregas por formularios de contacto, suscripción, compra o postulación, y los datos técnicos que se generan al navegar (dirección IP, identificadores de dispositivo, páginas visitadas, fecha y hora).', 'cumpleconsent' ) . '
'; if ( $ops ) { $h[] = '| ' . esc_html__( 'Finalidad', 'cumpleconsent' ) . ' | ' . esc_html__( 'Datos', 'cumpleconsent' ) . ' | ' . esc_html__( 'Base de licitud', 'cumpleconsent' ) . ' | ' . esc_html__( 'Titulares', 'cumpleconsent' ) . ' |
|---|---|---|---|
| ' . esc_html( (string) $op['finalidad'] ) . ' | ' . esc_html( (string) $op['datos'] ) . ' | ' . esc_html( (string) $op['base'] ) . ' | ' . esc_html( (string) $op['titulares'] ) . ' |
' . esc_html__( 'La base de licitud de cada tratamiento es el consentimiento que otorgas, salvo cuando la ley permite tratar los datos sin consentimiento (por ejemplo, para ejecutar un contrato contigo, cumplir una obligación legal o satisfacer un interés legítimo que no afecta tus derechos).', 'cumpleconsent' ) . '
'; // 3. Cookies y tecnologías similares. $h[] = '' . esc_html__( 'Usamos cookies y almacenamiento local del navegador con estas finalidades. Nada que no sea necesario para el funcionamiento del sitio se activa antes de que tú lo aceptes:', 'cumpleconsent' ) . '
'; $h[] = '' . esc_html__( 'Puedes aceptar todo, rechazar todo o elegir finalidad por finalidad en el aviso que aparece al entrar, y cambiar tu decisión cuando quieras desde el enlace “Preferencias de privacidad” del pie de página.', 'cumpleconsent' ) . '
'; // 4. Destinatarios (14 ter d) y 15 bis). $h[] = '' . esc_html__( 'No vendemos ni cedemos tus datos. Los comunicamos únicamente a proveedores que actúan por nuestra cuenta y siguiendo nuestras instrucciones (encargados del tratamiento), con contrato escrito que fija el objeto, la duración, las categorías de datos y las medidas de seguridad:', 'cumpleconsent' ) . '
'; if ( $transfers ) { $h[] = '' . esc_html__( 'Completa esta lista con tus proveedores (hosting, correo, analítica, publicidad, pagos) antes de publicar la política.', 'cumpleconsent' ) . '
'; } // 5. Transferencias internacionales (14 ter h) y art. 27). $h[] = '' . sprintf( /* translators: %s: listado de transferencias */ esc_html__( 'Algunos de nuestros proveedores tratan datos fuera de Chile. Estas son las transferencias y la garantía en que se amparan: %s. Cuando el país de destino no cuenta con un nivel adecuado de protección, la transferencia se ampara en cláusulas contractuales u otros instrumentos que establecen garantías adecuadas, o en tu consentimiento expreso cuando corresponda.', 'cumpleconsent' ), esc_html( implode( '; ', $rows ) ) ) . '
'; } else { $h[] = '' . esc_html__( 'No declaramos transferencias internacionales. Si usas servicios que tratan datos fuera de Chile (analítica, publicidad, correo, hosting), decláralas aquí: el art. 14 ter h) las obliga a estar en esta política.', 'cumpleconsent' ) . '
'; } // 6. Conservación (14 ter i)). $h[] = '' . sprintf( /* translators: %d: meses */ esc_html__( 'Conservamos los datos mientras exista la relación que los originó y, luego, durante los plazos legales aplicables. Los registros de consentimiento y de decisiones del aviso de privacidad se conservan por %d meses como prueba de que informamos y de que tú decidiste; cumplido ese plazo se eliminan automáticamente. Las solicitudes de derechos y sus respuestas se conservan por el mismo periodo, como respaldo de su tramitación.', 'cumpleconsent' ), $months ) . '
'; // 7. Origen (14 ter j)). $h[] = '' . esc_html__( 'Los datos que tratamos provienen de ti: los entregas voluntariamente en los formularios del sitio, o se generan automáticamente cuando lo navegas. No tratamos datos obtenidos de fuentes de acceso público para fines distintos de los informados, salvo que la ley lo permita y así se te informe.', 'cumpleconsent' ) . '
'; // 8. Decisiones automatizadas (14 ter l)). $h[] = '' . esc_html__( 'No adoptamos decisiones automatizadas que te afecten jurídicamente ni elaboramos perfiles con tus datos a partir de este sitio. Si en el futuro lo hiciéramos, te informaremos la lógica aplicada y las consecuencias previstas antes de que ocurra.', 'cumpleconsent' ) . '
'; // 9. Derechos (14 ter f) y art. 11). $h[] = '' . esc_html__( 'Puedes solicitar acceso a tus datos, su rectificación, su supresión (cancelación), oponerte a un tratamiento, pedir su portabilidad y solicitar el bloqueo temporal mientras se resuelve una rectificación, supresión u oposición.', 'cumpleconsent' ) . '
'; $h[] = '' . esc_html__( 'La solicitud se presenta por escrito por correo electrónico o por el formulario habilitado para este fin, individualizando quién la presenta, un medio para responderte y los datos o el tratamiento respecto de los cuales ejerces el derecho. Acusaremos recibo y te responderemos dentro de 30 días corridos, plazo que puede prorrogarse una sola vez por otros 30 días corridos. Si pides el bloqueo temporal, responderemos dentro de 2 días hábiles y, mientras no resolvamos, no trataremos los datos comprendidos en tu solicitud. En caso de denegación te indicaremos la causa y los antecedentes que la justifican.', 'cumpleconsent' ) . '
'; $h[] = '' . esc_html__( 'Ejercer estos derechos es gratuito y no necesitas patrocinio.', 'cumpleconsent' ) . '
'; if ( '' !== $email ) { $h[] = '' . sprintf( /* translators: %s: correo habilitado para recibir solicitudes de derechos. */ esc_html__( 'Presenta tu solicitud por el formulario habilitado en este sitio o escríbenos específicamente a %s.', 'cumpleconsent' ), '' . esc_html( $email ) . '' ) . '
'; } // 10. Retiro del consentimiento (14 ter k)). $h[] = '' . esc_html__( 'Si el tratamiento se basa en tu consentimiento, puedes retirarlo en cualquier momento y sin expresión de causa, desde el enlace “Preferencias de privacidad” del pie del sitio o escribiéndonos. Retirar el consentimiento no afecta la licitud del tratamiento que hicimos antes de retirarlo.', 'cumpleconsent' ) . '
'; // 11. Reclamo ante la Agencia (14 ter g)). $h[] = '' . esc_html__( 'Si rechazamos o no respondemos oportunamente tu solicitud, puedes presentar un reclamo ante la Agencia de Protección de Datos Personales dentro de 30 días hábiles, en los términos del artículo 41 de la Ley 21.719 y su normativa.', 'cumpleconsent' ) . '
'; // 12. Seguridad (14 ter e)). $h[] = '' . esc_html__( 'Aplicamos medidas técnicas y organizativas apropiadas al riesgo: conexión cifrada (HTTPS), control de acceso por roles, principio de mínima recolección, bloqueo de rastreadores antes de tu consentimiento, seudonimización y hash de los datos que se usan para evidencia, y plazos de conservación con borrado automático. Registramos los incidentes y, cuando corresponda, los reportamos a la Agencia y a las personas afectadas.', 'cumpleconsent' ) . '
'; // 13. Cambios (14 ter a)). $h[] = '' . esc_html__( 'Si cambiamos el contenido de esta política subiremos la versión y la fecha que aparecen al inicio. Si el cambio afecta las finalidades del tratamiento, volveremos a pedirte tu consentimiento antes de aplicarlo.', 'cumpleconsent' ) . '
'; $h[] = '' . esc_html__( 'Documento generado con CumpleConsent a partir de la configuración del sitio. Revísalo, completa los corchetes y ajústalo a tu operación real: la política es tuya y el responsable eres tú.', 'cumpleconsent' ) . '
'; return implode( "\n", $h ); } /** * Crea (o actualiza) la página de la política con el texto generado. * * @param bool $publish Si se publica de inmediato. * @return int ID de la página, 0 si falló. */ /** Marca en la página que indica que ese texto lo generó este plugin. */ const GENERATED_META = '_cumpleconsent_generated'; /** ¿El texto de esta página lo escribió el plugin? */ public static function is_generated( int $page_id ): bool { if ( $page_id <= 0 ) { return false; } if ( (int) Settings::get( 'policy_generated_id', 0 ) === $page_id ) { return true; } return '' !== (string) get_post_meta( $page_id, self::GENERATED_META, true ); } public static function create_page( bool $publish = false ): int { $content = self::generated_text(); $page_id = (int) Settings::get( 'policy_page_id', 0 ); // Si no hay página asignada pero ya existe una con el nombre habitual, se // reutiliza: generar una segunda dejaría el sitio con dos políticas y una // de ellas sin actualizar (y con un slug feo tipo -2). if ( ! $page_id ) { $reutilizable = get_page_by_path( 'politica-de-privacidad' ); if ( $reutilizable instanceof \WP_Post ) { $page_id = (int) $reutilizable->ID; Settings::save( array( 'policy_page_id' => $page_id ) ); } } $existing = $page_id ? get_post( $page_id ) : null; if ( $existing ) { // Nunca se pisa una política que no haya escrito este plugin: la del sitio // puede ser un documento propio, revisado y publicado, y reemplazarlo por // el texto genérico sería destruir trabajo ajeno. Si no es nuestra, el // texto nuevo va a un borrador aparte y el panel lo explica. if ( ! self::is_generated( (int) $existing->ID ) ) { return self::save_draft( $content ); } wp_update_post( array( 'ID' => $existing->ID, 'post_content' => $content, 'post_status' => $publish ? 'publish' : $existing->post_status, ) ); update_post_meta( (int) $existing->ID, self::GENERATED_META, CUMPLECONSENT_VERSION ); Settings::save( array( 'policy_last_mode' => 'actualizada' ) ); return (int) $existing->ID; } $new_id = wp_insert_post( array( 'post_title' => __( 'Política de privacidad', 'cumpleconsent' ), 'post_content' => $content, 'post_status' => $publish ? 'publish' : 'draft', 'post_type' => 'page', 'post_author' => get_current_user_id(), ), true ); if ( is_wp_error( $new_id ) ) { Settings::save( array( 'policy_last_mode' => 'error' ) ); return 0; } update_post_meta( (int) $new_id, self::GENERATED_META, CUMPLECONSENT_VERSION ); Settings::save( array( 'policy_page_id' => (int) $new_id, 'policy_last_mode' => 'nueva' ) ); return (int) $new_id; } /** * Guarda el texto generado como borrador aparte, sin tocar la política del * sitio: es lo que ocurre cuando la página asignada no la escribió el plugin. * * @param string $content Texto generado. * @return int Id del borrador (0 si falló). */ private static function save_draft( string $content ): int { $draft = wp_insert_post( array( 'post_title' => __( 'Política de privacidad (borrador de CumpleConsent)', 'cumpleconsent' ), 'post_content' => $content, 'post_status' => 'draft', 'post_type' => 'page', 'post_author' => get_current_user_id(), ), true ); if ( is_wp_error( $draft ) ) { Settings::save( array( 'policy_last_mode' => 'error' ) ); return 0; } update_post_meta( (int) $draft, self::GENERATED_META, CUMPLECONSENT_VERSION ); Settings::save( array( 'policy_draft_id' => (int) $draft, 'policy_last_mode' => 'borrador' ) ); return (int) $draft; } // ── Verificador (art. 14 ter) ──────────────────────────────────────────── /** Texto de la política sobre el que se verifica (página publicada o generador). */ public static function verification_text(): string { $page_id = self::linked_page_id(); $post = $page_id ? get_post( $page_id ) : null; if ( $post ) { return self::page_text( $page_id ); } // Sin política publicada no se verifica nada: puntuar el texto que el plugin // genera por su cuenta daría un 100 % de una página que el sitio no tiene. return ''; } /** * Texto visible de un HTML de página, sin el contenido de |$)#is', ' ', $html ); $html = (string) preg_replace( '#|$)#is', ' ', $html ); return wp_strip_all_tags( strip_shortcodes( $html ) ); } /** * Verifica los doce literales del art. 14 ter. * * @return array