' . 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

', esc_html__( 'Ajustes guardados.', 'digifest' ) ); } elseif ( 'license_ok' === $notice ) { printf( '

%s

', esc_html__( 'Licencia activada correctamente. Ya puedes usar las funciones Pro.', 'digifest' ) ); } elseif ( 0 === strpos( $notice, 'license_checked' ) ) { printf( '

%s

', esc_html__( 'Comprobación completada. Licencia válida.', 'digifest' ) ); } elseif ( 0 === strpos( $notice, 'license_error:' ) ) { $message = substr( $notice, strlen( 'license_error:' ) ); printf( '

%s %s

', esc_html__( 'Error de licencia:', 'digifest' ), esc_html( $message ) ); } } /** * Render de la página con pestañas. */ public static function render() { if ( ! current_user_can( 'manage_options' ) ) { return; } $tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'effects'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( ! in_array( $tab, array( 'effects', 'license', 'general' ), true ) ) { $tab = 'effects'; } echo '
'; echo '

DigiFest

'; echo '

' . esc_html__( 'Efectos estacionales para tu tienda: activa Halloween, Navidad y más, de forma manual o programada.', 'digifest' ) . '

'; self::render_notice(); echo ''; if ( 'effects' === $tab ) { self::render_effects_tab(); } elseif ( 'license' === $tab ) { self::render_license_tab(); } else { self::render_general_tab(); } echo '
'; } /** * Pestaña Efectos: una tarjeta por tema. */ private static function render_effects_tab() { $themes = DigiFest_Effects::get_themes(); $is_pro = DigiFest_License::is_pro(); echo '
'; wp_nonce_field( self::NONCE ); echo ''; echo '
'; foreach ( $themes as $slug => $theme ) { $s = DigiFest_Effects::get_theme_settings( $slug ); $active = DigiFest_Effects::is_theme_active( $slug ); $inseason = DigiFest_Effects::is_in_season( $slug ); echo '
'; echo '
'; echo '' . esc_html( $theme['icon'] ) . ''; echo '

' . esc_html( $theme['label'] ) . '

'; echo '' . ( $active ? esc_html__( 'Activo', 'digifest' ) : ( $inseason ? esc_html__( 'En temporada (esperando activación)', 'digifest' ) : esc_html__( 'Inactivo', 'digifest' ) ) ) . ''; echo '
'; // Activación. echo '
'; echo ''; echo ''; echo '
'; // Fechas. echo '
'; echo ''; echo ''; echo ''; echo '

' . esc_html__( 'Formato MM-DD (mes-día). Se repite cada año en ese periodo. Si el inicio es posterior al fin, el rango cruza el año nuevo.', 'digifest' ) . '

'; echo '
'; // Densidad. echo '
'; echo ''; echo ''; echo '
'; // Zoom-susto. if ( 'halloween' === $slug ) { echo '
'; echo ''; echo '
'; } // Efectos de ambiente: telarañas, luces, banderines... if ( ! empty( $theme['ambient_sprites'] ) ) { echo '
'; echo ''; echo '
'; } // Tradiciones catalanas (Caga Tió, Caganer, Estrella). if ( ! empty( $theme['catalan_sprites'] ) ) { echo '
'; echo ''; echo '
'; } // Banner WooCommerce. echo '
'; echo ''; echo ''; echo '
'; echo ''; echo ''; echo '
'; echo '
'; echo '
'; // .df-card } echo '
'; // .df-cards // Banner informativo sobre temas adicionales Pro disponibles externamente echo '
'; echo '
✨ ' . esc_html__( 'MÁS FESTIVIDADES DISPONIBLES', 'digifest' ) . '
'; echo '

' . esc_html__( '¿Quieres celebrar más fechas a lo largo de todo el año?', 'digifest' ) . '

'; echo '

' . esc_html__( 'Desbloquea temas festivos adicionales (San Valentín, Año Nuevo, Pascua, San Patricio, Primavera, Verano, Otoño, Black Friday y Carnaval) con DigiFest Pro.', 'digifest' ) . '

'; echo ''; echo '
'; echo '

' . esc_html__( 'Nota: si varios temas están activos a la vez, solo se muestra el primero de la lista.', 'digifest' ) . '

'; submit_button( __( 'Guardar cambios', 'digifest' ) ); echo '
'; } /** * Pestaña Licencia. */ private static function render_license_tab() { echo '
'; echo '
'; echo '
✨ ' . esc_html__( 'DESBLOQUEA TODO EL AÑO', 'digifest' ) . '
'; echo '

' . esc_html__( 'Lleva la ambientación de tu tienda al siguiente nivel con DigiFest Pro', 'digifest' ) . '

'; 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 '
'; echo '

' . esc_html__( 'Festividades incluidas en la versión Pro:', 'digifest' ) . '

'; echo '
    '; echo '
  • ' . esc_html__( 'San Valentín (14 Feb)', 'digifest' ) . ': ' . esc_html__( 'Corazones flotantes, cupidos, cartas de amor y guirnalda.', 'digifest' ) . '
  • '; echo '
  • ' . esc_html__( 'Fin de Año (31 Dic)', 'digifest' ) . ': ' . esc_html__( 'Confeti multicolor, fuegos artificiales, champán y estrellas doradas.', 'digifest' ) . '
  • '; echo '
  • ' . esc_html__( 'Pascua', 'digifest' ) . ': ' . esc_html__( 'Huevos de Pascua decorados, conejitos y mariposas primaverales.', 'digifest' ) . '
  • '; echo '
  • ' . esc_html__( 'San Patricio (17 Mar)', 'digifest' ) . ': ' . esc_html__( 'Tréboles de cuatro hojas, monedas de oro, sombreros y arcoíris.', 'digifest' ) . '
  • '; echo '
  • ' . esc_html__( 'Primavera & Sakura', 'digifest' ) . ': ' . esc_html__( 'Pétalos de cerezo flotantes, flores silvestres, abejas y rama florecida.', 'digifest' ) . '
  • '; echo '
  • ' . esc_html__( 'Verano', 'digifest' ) . ': ' . esc_html__( 'Soles brillantes, palmeras, helados, gaviotas y olas en el pie de página.', 'digifest' ) . '
  • '; echo '
  • ' . esc_html__( 'Otoño & Castanyada', 'digifest' ) . ': ' . esc_html__( 'Hojas doradas y rojas de arce, castañas asadas y bellotas.', 'digifest' ) . '
  • '; echo '
  • ' . esc_html__( 'Black Friday', 'digifest' ) . ': ' . esc_html__( 'Etiquetas de descuento, cajas de regalo y cintas de oferta.', 'digifest' ) . '
  • '; echo '
  • ' . esc_html__( 'Carnaval', 'digifest' ) . ': ' . esc_html__( 'Máscaras venecianas, serpentinas, maracas y banderines festivos.', 'digifest' ) . '
  • '; echo '
'; echo '
'; echo ''; 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 '
'; // .df-upgrade-card echo '
'; // .df-license-box } /** * Pestaña Ajustes generales. */ private static function render_general_tab() { $general = DigiFest_Effects::get_settings()['general']; $banner = DigiFest_Effects::get_settings()['banner']; echo '
'; wp_nonce_field( self::NONCE ); echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo '
' . esc_html__( 'Móvil', 'digifest' ) . ''; echo ''; echo '
' . esc_html__( 'Interacción', 'digifest' ) . ''; echo ''; echo '

' . esc_html__( 'Al hacer clic en cualquier enlace, botón o elemento de la web, brota una pequeña ráfaga de chispitas del tema activo.', 'digifest' ) . '

'; echo '
'; printf( '', esc_attr( $general['z_index'] ) ); echo '

' . esc_html__( 'Capa donde se dibujan los efectos. Sube el valor si algún elemento de tu tema los tapa.', 'digifest' ) . '

'; echo '
'; printf( '', esc_attr( $general['excluded_pages'] ) ); echo '

' . esc_html__( 'IDs de páginas separados por comas donde NO se mostrarán los efectos ni el banner.', 'digifest' ) . '

'; echo '
' . esc_html__( 'Banner de tienda', 'digifest' ) . ''; echo '
'; echo ''; echo '
'; submit_button( __( 'Guardar cambios', 'digifest' ) ); echo '
'; } }