' . esc_html__( 'Ajustes', 'digifest' ) . '' ); return $links; } /** * CSS/JS del admin. * * @param string $hook Hook actual. */ public static function assets( $hook ) { if ( false === strpos( (string) $hook, self::MENU_SLUG ) ) { return; } wp_enqueue_style( 'digifest-admin', DIGIFEST_URL . 'assets/css/df-admin.css', array(), DIGIFEST_VERSION ); wp_enqueue_script( 'digifest-admin', DIGIFEST_URL . 'assets/js/df-admin.js', array(), DIGIFEST_VERSION, true ); wp_localize_script( 'digifest-admin', 'DIGIFEST_ADMIN', array( 'confirmDeactivate' => __( '¿Seguro que quieres desactivar la licencia en este sitio?', 'digifest' ), ) ); } /** * Procesa el guardado de cualquiera de las pestañas. */ public static function save() { if ( ! isset( $_POST['digifest_form'] ) || ! current_user_can( 'manage_options' ) ) { return; } check_admin_referer( self::NONCE ); $form = sanitize_key( wp_unslash( $_POST['digifest_form'] ) ); if ( 'settings' === $form ) { self::save_settings(); } elseif ( 'license' === $form ) { self::save_license(); } } /** * Guarda la configuración de efectos y ajustes generales. */ private static function save_settings() { check_admin_referer( self::NONCE ); $current = DigiFest_Effects::get_settings(); $themes = DigiFest_Effects::get_themes(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- El array se sanea elemento a elemento a continuación. $input = isset( $_POST['df'] ) && is_array( $_POST['df'] ) ? (array) wp_unslash( $_POST['df'] ) : array(); // Ajustes generales y del banner. $general = $current['general']; if ( isset( $input['general'] ) ) { $g = $input['general']; $general['show_mobile'] = ! empty( $g['show_mobile'] ); $general['click_sparkles'] = ! empty( $g['click_sparkles'] ); $general['z_index'] = isset( $g['z_index'] ) ? absint( $g['z_index'] ) : 999999; $general['excluded_pages'] = isset( $g['excluded_pages'] ) ? sanitize_text_field( $g['excluded_pages'] ) : ''; } $banner = $current['banner']; if ( isset( $input['banner'] ) ) { $banner['dismissible'] = ! empty( $input['banner']['dismissible'] ); $banner['sticky'] = ! empty( $input['banner']['sticky'] ); } // Configuración por tema. $themes_out = $current['themes']; foreach ( $themes as $slug => $theme ) { if ( ! isset( $input['themes'][ $slug ] ) ) { continue; } $t = $input['themes'][ $slug]; $defaults = DigiFest_Effects::default_settings()['themes'][ $slug ]; $prev = $themes_out[ $slug ]; $themes_out[ $slug ] = array( 'enabled' => ! empty( $t['enabled'] ), 'auto' => ! empty( $t['auto'] ), 'start' => self::sanitize_mmdd( $t['start'] ?? '', $defaults['start'] ), 'end' => self::sanitize_mmdd( $t['end'] ?? '', $defaults['end'] ), 'density' => in_array( $t['density'] ?? '', array( 'low', 'medium', 'high' ), true ) ? $t['density'] : 'medium', 'scare' => ! empty( $t['scare'] ), 'ambient' => ! empty( $t['ambient'] ), 'catalan' => ! empty( $t['catalan'] ), 'location' => in_array( $t['location'] ?? '', array( 'all', 'home', 'shop' ), true ) ? $t['location'] : 'all', 'banner' => ! empty( $t['banner'] ), 'banner_text' => isset( $t['banner_text'] ) ? wp_kses_post( $t['banner_text'] ) : $prev['banner_text'], 'banner_bg' => self::sanitize_color( $t['banner_bg'] ?? '', $defaults['banner_bg'] ), 'banner_color' => self::sanitize_color( $t['banner_color'] ?? '', $defaults['banner_color'] ), ); } update_option( 'digifest_settings', array( 'general' => $general, 'banner' => $banner, 'themes' => $themes_out, ) ); self::redirect_with_notice( 'settings', 'saved' ); } /** * Valida un campo MM-DD; si no es válido, devuelve el fallback. */ private static function sanitize_mmdd( $value, $fallback ) { $value = sanitize_text_field( $value ); return preg_match( '/^(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/', $value ) ? $value : $fallback; } /** * Valida un color hex; si no es válido, devuelve el fallback. */ private static function sanitize_color( $value, $fallback ) { $value = sanitize_text_field( $value ); return preg_match( '/^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/', $value ) ? $value : $fallback; } /** * Procesa acciones de licencia: activar (directa o Envato) / desactivar. */ private static function save_license() { check_admin_referer( self::NONCE ); $action = isset( $_POST['digifest_license_action'] ) ? sanitize_key( wp_unslash( $_POST['digifest_license_action'] ) ) : ''; if ( 'activate_direct' === $action ) { $key = sanitize_text_field( wp_unslash( $_POST['digifest_license_key'] ?? '' ) ); $result = $key ? DigiFest_License::activate( $key ) : array( 'success' => false, 'message' => __( 'Introduce una clave de licencia.', 'digifest' ) ); } elseif ( 'activate_envato' === $action ) { $code = sanitize_text_field( wp_unslash( $_POST['digifest_purchase_code'] ?? '' ) ); $result = $code ? DigiFest_License::activate_envato( $code ) : array( 'success' => false, 'message' => __( 'Introduce el purchase code de Envato.', 'digifest' ) ); } elseif ( 'deactivate' === $action ) { $result = DigiFest_License::deactivate(); } elseif ( 'force_check' === $action ) { // Botón "Verificar estado de la licencia": fuerza check() saltando el caché. $result = DigiFest_License::check( true ); if ( ! empty( $result['success'] ) ) { $notice = 'license_checked'; } else { $notice = 'license_error:' . ( $result['message'] ?? __( 'Error desconocido.', 'digifest' ) ); } self::redirect_with_notice( 'license', $notice ); } else { return; } $notice = ! empty( $result['success'] ) ? 'license_ok' : 'license_error:' . ( $result['message'] ?? __( 'Error desconocido.', 'digifest' ) ); self::redirect_with_notice( 'license', $notice ); } /** * Redirige de vuelta a la pestaña con un aviso. */ private static function redirect_with_notice( $tab, $notice ) { wp_safe_redirect( add_query_arg( array( 'page' => self::MENU_SLUG, 'tab' => $tab, 'digifest_notice' => $notice, // add_query_arg ya codifica el valor. ), admin_url( 'admin.php' ) ) ); exit; } /** * Imprime el aviso (guardado / licencia). */ private static function render_notice() { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Parámetro GET de solo lectura para mostrar un aviso tras redirección. if ( ! isset( $_GET['digifest_notice'] ) ) { return; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended $raw_notice = sanitize_text_field( wp_unslash( $_GET['digifest_notice'] ) ); $notice = sanitize_text_field( rawurldecode( $raw_notice ) ); if ( 'saved' === $notice ) { printf( '
%s
%s
%s
%s %s
' . esc_html__( 'Efectos estacionales para tu tienda: activa Halloween, Navidad y más, de forma manual o programada.', 'digifest' ) . '
'; self::render_notice(); echo '' . esc_html__( 'La versión gratuita incluye Halloween y Navidad completamente funcionales. Con DigiFest Pro desbloqueas el calendario anual completo con 9 festividades adicionales, decoración de ambiente a pantalla completa y chispitas interactivas para deleitar a tus clientes y maximizar tus conversiones.', 'digifest' ) . '
'; echo ''; printf( /* translators: 1: URL de la web oficial, 2: URL de soporte */ wp_kses_post( __( 'Al adquirir tu licencia en festivo.digitalinnovationglobal.com recibirás la versión completa DigiFest Pro lista para instalar en tu WordPress. ¿Dudas o preguntas? Abre un ticket en el portal de soporte.', 'digifest' ) ), esc_url( 'https://festivo.digitalinnovationglobal.com/' ), esc_url( 'https://licencias.digitalinnovationglobal.com/tickets/new' ) ); echo '
'; echo '