Privacidad). */ public static function texto_privacidad() { if ( ! function_exists( 'wp_add_privacy_policy_content' ) ) { return; } $texto = '
' . __( 'Esta web utiliza DigaChat, un asistente virtual con inteligencia artificial que responde a las consultas que se escriben en el chat. Los mensajes del chat se envían al servicio de DigaChat, que actúa como encargado del tratamiento, solo para generar la respuesta y mejorar la atención. No escriba en el chat datos de pago ni datos personales sensibles. Si un visitante pide que la tienda le responda personalmente, el asistente le pide su nombre, su email y, de forma opcional, su teléfono, y los envía por email al responsable de la web solo para contestarle. Si un cliente pregunta por un pedido, el asistente le pide el número de pedido y el email de compra, y solo le muestra el estado, las fechas, los productos y el seguimiento del envío si ambos coinciden. Si un visitante pide recibir la conversación por email, su dirección se usa solo para ese envío y, si el responsable de la web lo tiene activado, este recibe una copia. Las conversaciones y estos datos se conservan durante un máximo de 12 meses. Si la tienda tiene activados los avisos de carrito abandonado, al escribir el email en la página de pago se guardan ese email (y, si se escriben, el teléfono y el nombre) junto con el contenido del carrito, para enviar como máximo dos recordatorios por email si la compra no se termina. Estos datos se borran al completar la compra, al pedir la baja desde el enlace de los emails o, como máximo, siete días después del último recordatorio.', 'digachat' ) . '
'; wp_add_privacy_policy_content( 'DigaChat', wp_kses_post( $texto ) ); } /** * URL de una pestaña. * * @param string $pestana conexion, asistente o uso. * @return string */ public static function url( $pestana = 'conexion' ) { return admin_url( 'admin.php?page=digachat&tab=' . $pestana ); } /** * Guarda un aviso para mostrarlo tras la redirección. * * @param string $tipo success, error o warning. * @param string $mensaje Texto. */ public static function aviso( $tipo, $mensaje ) { set_transient( 'digachat_aviso_' . get_current_user_id(), array( 'tipo' => $tipo, 'mensaje' => $mensaje, ), 60 ); } /** * Comprueba permisos y nonce de una acción. * * @param string $accion Nombre de la acción. */ public static function comprobar( $accion ) { self::permiso(); check_admin_referer( $accion ); } /** * Corta la acción si el usuario no puede gestionar DigaChat. */ public static function permiso() { if ( ! current_user_can( self::CAP ) ) { wp_die( esc_html__( 'No tiene permisos para hacer esto.', 'digachat' ) ); } } /** * Alta de la tienda en el servicio. */ public static function conectar() { self::permiso(); check_admin_referer( 'digachat_conectar' ); $email = isset( $_POST['email'] ) ? sanitize_email( wp_unslash( $_POST['email'] ) ) : ''; $consentimito = ! empty( $_POST['consentimiento'] ); if ( ! is_email( $email ) ) { self::aviso( 'error', __( 'Escriba un email válido.', 'digachat' ) ); wp_safe_redirect( self::url() ); exit; } if ( ! $consentimito ) { self::aviso( 'error', __( 'Para conectar la web tiene que aceptar las condiciones del servicio.', 'digachat' ) ); wp_safe_redirect( self::url() ); exit; } if ( 0 !== strpos( home_url(), 'https://' ) && apply_filters( 'digachat_requiere_https', true ) ) { self::aviso( 'error', __( 'DigaChat necesita que la web funcione con https.', 'digachat' ) ); wp_safe_redirect( self::url() ); exit; } $resultado = DigaChat_Api::alta( $email ); if ( is_wp_error( $resultado ) ) { self::aviso( 'error', $resultado->get_error_message() ); wp_safe_redirect( self::url() ); exit; } DigaChat_Settings::update( array( 'clave' => sanitize_text_field( $resultado['clave'] ), 'email' => $email, 'plan' => isset( $resultado['plan'] ) ? sanitize_key( $resultado['plan'] ) : 'gratis', 'solo_admin' => true, // Modo prueba: solo lo ven los administradores hasta que se desmarque. ) ); if ( '' === DigaChat_Settings::get( 'info_tienda' ) ) { DigaChat_Settings::update( array( 'info_tienda' => self::info_automatica() ) ); } DigaChat_Api::enviar_config(); self::aviso( 'success', __( 'Web conectada. Revise la información del asistente y guárdela.', 'digachat' ) ); wp_safe_redirect( self::url( 'asistente' ) ); exit; } /** * Quita la conexión en esta web. */ public static function desconectar() { self::permiso(); check_admin_referer( 'digachat_desconectar' ); DigaChat_Settings::update( array( 'clave' => '' ) ); self::aviso( 'success', __( 'Web desconectada. El chat ya no aparece en ella.', 'digachat' ) ); wp_safe_redirect( self::url() ); exit; } /** * Guarda los ajustes del asistente y los envía al servicio. */ public static function guardar() { self::permiso(); check_admin_referer( 'digachat_guardar' ); $posicion = isset( $_POST['posicion'] ) ? sanitize_key( wp_unslash( $_POST['posicion'] ) ) : 'derecha'; $color = isset( $_POST['color'] ) ? sanitize_hex_color( wp_unslash( $_POST['color'] ) ) : ''; $info = isset( $_POST['info_tienda'] ) ? sanitize_textarea_field( wp_unslash( $_POST['info_tienda'] ) ) : ''; $tipo = isset( $_POST['tipo'] ) ? sanitize_key( wp_unslash( $_POST['tipo'] ) ) : 'tienda'; $trato = isset( $_POST['trato'] ) ? sanitize_key( wp_unslash( $_POST['trato'] ) ) : 'usted'; $whatsapp = isset( $_POST['whatsapp'] ) ? DigaChat_Settings::normalizar_telefono( sanitize_text_field( wp_unslash( $_POST['whatsapp'] ) ) ) : ''; DigaChat_Settings::update( array( 'activo' => ! empty( $_POST['activo'] ), 'tipo' => in_array( $tipo, array( 'tienda', 'servicios' ), true ) ? $tipo : 'tienda', 'trato' => in_array( $trato, array( 'usted', 'tu' ), true ) ? $trato : 'usted', 'solo_admin' => ! empty( $_POST['solo_admin'] ), 'nombre_asistente' => isset( $_POST['nombre_asistente'] ) ? self::recortar( sanitize_text_field( wp_unslash( $_POST['nombre_asistente'] ) ), 60 ) : '', 'bienvenida' => isset( $_POST['bienvenida'] ) ? self::recortar( sanitize_text_field( wp_unslash( $_POST['bienvenida'] ) ), 300 ) : '', 'info_tienda' => self::recortar( $info, 8000 ), 'color' => $color ? $color : '#1f6f5c', 'posicion' => in_array( $posicion, array( 'derecha', 'izquierda' ), true ) ? $posicion : 'derecha', 'contacto' => isset( $_POST['contacto'] ) ? sanitize_email( wp_unslash( $_POST['contacto'] ) ) : '', 'contactos' => ! empty( $_POST['contactos'] ), 'email_avisos' => isset( $_POST['email_avisos'] ) ? sanitize_email( wp_unslash( $_POST['email_avisos'] ) ) : '', 'copia_conversaciones' => ! empty( $_POST['copia_conversaciones'] ), 'plazo_entrega' => isset( $_POST['plazo_entrega'] ) ? max( 0, min( 60, absint( $_POST['plazo_entrega'] ) ) ) : 0, 'whatsapp' => $whatsapp, 'ocultar_whatsapp' => ! empty( $_POST['ocultar_whatsapp'] ), 'mensaje_whatsapp' => isset( $_POST['mensaje_whatsapp'] ) ? self::recortar( sanitize_text_field( wp_unslash( $_POST['mensaje_whatsapp'] ) ), 200 ) : '', ) ); if ( DigaChat_Settings::conectado() ) { $envio = DigaChat_Api::enviar_config(); if ( is_wp_error( $envio ) ) { self::aviso( 'warning', __( 'Ajustes guardados en la web, pero no se han podido enviar al servicio: ', 'digachat' ) . $envio->get_error_message() ); } else { self::aviso( 'success', __( 'Ajustes guardados. El asistente ya usa la nueva información.', 'digachat' ) ); } } else { self::aviso( 'success', __( 'Ajustes guardados.', 'digachat' ) ); } wp_safe_redirect( self::url( 'asistente' ) ); exit; } /** * Rellena la información de la tienda a partir de WooCommerce y las páginas legales. */ public static function autorrellenar() { self::permiso(); check_admin_referer( 'digachat_autorrellenar' ); DigaChat_Settings::update( array( 'info_tienda' => self::info_automatica() ) ); self::aviso( 'warning', __( 'Información rellenada a partir de WooCommerce y sus páginas legales. Revísela, corrija lo que haga falta y pulse «Guardar cambios».', 'digachat' ) ); wp_safe_redirect( self::url( 'asistente' ) ); exit; } /** * Recorta un texto respetando caracteres multibyte. * * @param string $texto Texto. * @param int $max Longitud máxima. * @return string */ private static function recortar( $texto, $max ) { return function_exists( 'mb_substr' ) ? mb_substr( $texto, 0, $max ) : substr( $texto, 0, $max ); } /** * Texto plano de una página, recortado. * * @param int $id ID de la página. * @param int $max Longitud máxima. * @return string */ private static function texto_pagina( $id, $max ) { $id = (int) $id; if ( $id <= 0 ) { return ''; } $pagina = get_post( $id ); if ( ! $pagina || 'publish' !== $pagina->post_status ) { return ''; } $texto = wp_strip_all_tags( strip_shortcodes( $pagina->post_content ) ); $texto = trim( preg_replace( '/\s+/', ' ', $texto ) ); if ( '' === $texto ) { return ''; } $recortado = self::recortar( $texto, $max ); return $recortado . ( strlen( $recortado ) < strlen( $texto ) ? '…' : '' ); } /** * Precio en texto plano (wc_price devuelve HTML con entidades). * * @param float $importe Importe. * @return string */ private static function precio( $importe ) { $texto = html_entity_decode( wp_strip_all_tags( wc_price( $importe ) ), ENT_QUOTES, 'UTF-8' ); return trim( str_replace( "\xC2\xA0", ' ', $texto ) ); } /** * IVA (u otro impuesto) de un coste de envío, con los tipos de la dirección de la tienda, * para dar al cliente el precio final que verá al pagar. * * @param float $coste Coste del envío sin impuestos. * @return float */ private static function impuesto_envio( $coste ) { if ( ! wc_tax_enabled() || ! class_exists( 'WC_Tax' ) ) { return 0.0; } $tipos = WC_Tax::find_shipping_rates( array( 'country' => WC()->countries->get_base_country(), 'state' => WC()->countries->get_base_state(), 'postcode' => WC()->countries->get_base_postcode(), 'city' => WC()->countries->get_base_city(), 'tax_class' => '', ) ); return $tipos ? (float) array_sum( WC_Tax::calc_tax( $coste, $tipos, false ) ) : 0.0; } /** * Construye la información de la tienda para el asistente. * * @return string */ public static function info_automatica() { $lineas = array(); if ( ! DigaChat_Settings::es_tienda() ) { $lineas[] = sprintf( /* translators: %s: nombre de la web */ __( 'Empresa: %s.', 'digachat' ), get_bloginfo( 'name' ) ); $lema = trim( wp_strip_all_tags( get_bloginfo( 'description' ) ) ); if ( '' !== $lema ) { $lineas[] = sprintf( /* translators: %s: lema de la web */ __( 'Qué hacemos: %s.', 'digachat' ), $lema ); } $lineas[] = __( 'Servicios: (escriba aquí los servicios que ofrece, a quién se dirigen y cómo se contratan).', 'digachat' ); $lineas[] = sprintf( /* translators: %s: email de contacto */ __( 'Contacto: %s.', 'digachat' ), DigaChat_Settings::contacto() ); return implode( "\n", $lineas ); } $lineas[] = sprintf( /* translators: %s: nombre de la tienda */ __( 'Tienda: %s.', 'digachat' ), get_bloginfo( 'name' ) ); $lineas[] = sprintf( /* translators: %s: email de contacto */ __( 'Contacto: %s.', 'digachat' ), DigaChat_Settings::contacto() ); if ( class_exists( 'WC_Shipping_Zones' ) ) { $envios = array(); foreach ( WC_Shipping_Zones::get_zones() as $zona_datos ) { $zona = WC_Shipping_Zones::get_zone( $zona_datos['id'] ); $metodos = array(); foreach ( $zona->get_shipping_methods( true ) as $metodo ) { $texto = $metodo->get_title(); if ( 'flat_rate' === $metodo->id ) { $coste = $metodo->get_option( 'cost' ); if ( '' !== $coste && is_numeric( str_replace( ',', '.', $coste ) ) ) { $coste = (float) str_replace( ',', '.', $coste ); if ( 'taxable' === $metodo->get_option( 'tax_status' ) ) { $coste += self::impuesto_envio( $coste ); } $texto .= ' ' . self::precio( $coste ); } } if ( 'free_shipping' === $metodo->id ) { $minimo = $metodo->get_option( 'min_amount' ); if ( '' !== $minimo && (float) $minimo > 0 ) { /* translators: %s: importe mínimo. */ $texto .= ' ' . sprintf( __( 'a partir de %s', 'digachat' ), self::precio( (float) $minimo ) ); } } $metodos[] = $texto; } if ( $metodos ) { $envios[] = $zona->get_zone_name() . ' (' . wp_strip_all_tags( $zona->get_formatted_location( 20 ) ) . '): ' . implode( '; ', $metodos ); } } if ( $envios ) { $lineas[] = __( 'Envíos (solo a estas zonas):', 'digachat' ); foreach ( $envios as $envio ) { $lineas[] = '- ' . $envio; } } } if ( function_exists( 'WC' ) && WC()->payment_gateways() ) { $pagos = array(); foreach ( WC()->payment_gateways()->payment_gateways() as $pasarela ) { if ( 'yes' === $pasarela->enabled ) { $pagos[] = wp_strip_all_tags( $pasarela->get_title() ); } } if ( $pagos ) { $lineas[] = sprintf( /* translators: %s: lista de formas de pago */ __( 'Formas de pago: %s.', 'digachat' ), implode( ', ', $pagos ) ); } } if ( function_exists( 'wc_get_page_id' ) ) { $devoluciones = self::texto_pagina( wc_get_page_id( 'refund_returns' ), 2500 ); if ( '' !== $devoluciones ) { $lineas[] = __( 'Devoluciones (texto de la web):', 'digachat' ) . ' ' . $devoluciones; } } return self::recortar( implode( "\n", $lineas ), 8000 ); } /** * Pantalla principal con pestañas. */ public static function pagina() { if ( ! current_user_can( self::CAP ) ) { return; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Solo selecciona la pestaña. $pestana = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'conexion'; $pestanas = array( 'conexion' => __( 'Conexión', 'digachat' ), 'asistente' => __( 'Asistente', 'digachat' ), ); if ( DigaChat_Settings::conectado() ) { /** * Pestañas adicionales (por ejemplo, las de un complemento). Clave => nombre visible. * El contenido se pinta con la acción «digachat_pestana_{clave}». * * @param array $pestanas Pestañas. */ $extra = (array) apply_filters( 'digachat_pestanas', array() ); $pestanas = array_merge( $pestanas, array_diff_key( $extra, array_flip( array( 'conexion', 'asistente', 'uso' ) ) ) ); $pestanas['uso'] = __( 'Uso y planes', 'digachat' ); } if ( ! isset( $pestanas[ $pestana ] ) ) { $pestana = 'conexion'; } $aviso = get_transient( 'digachat_aviso_' . get_current_user_id() ); delete_transient( 'digachat_aviso_' . get_current_user_id() ); ?>' . esc_html( $ajustes['email'] ) . '', '' . esc_html( self::nombre_plan( $ajustes['plan'] ) ) . '' ); ?>
' . esc_html( $uso->get_error_message() ) . '
'; return; } $usadas = isset( $uso['usadas'] ) ? (int) $uso['usadas'] : 0; $limite = isset( $uso['limite'] ) ? max( 1, (int) $uso['limite'] ) : 1; $plan = isset( $uso['plan'] ) ? sanitize_key( $uso['plan'] ) : 'gratis'; $porcentaje = min( 100, round( $usadas * 100 / $limite ) ); $ultimas = isset( $uso['ultimas'] ) && is_array( $uso['ultimas'] ) ? $uso['ultimas'] : array(); if ( $plan !== DigaChat_Settings::get( 'plan' ) ) { DigaChat_Settings::update( array( 'plan' => $plan ) ); } ?>' . esc_html( number_format_i18n( $usadas ) ) . '', esc_html( number_format_i18n( $limite ) ) ); ?>