Changeset 3675014
- Timestamp:
- 08/31/2026 10:38:29 PM (7 weeks ago)
- Location:
- la-terreta-food-labels-for-woocommerce
- Files:
-
- 54 deleted
- 12 edited
- 1 copied
-
tags/3.1.8 (copied) (copied from la-terreta-food-labels-for-woocommerce/trunk )
-
tags/3.1.8/la-terreta-food-labels-for-woocommerce.php (modified) (9 diffs)
-
tags/3.1.8/lib/design.php (modified) (1 diff)
-
tags/3.1.8/lib/functions.php (modified) (2 diffs)
-
tags/3.1.8/lib/menu.php (modified) (5 diffs)
-
tags/3.1.8/readme.txt (modified) (4 diffs)
-
tags/3.1.8/vendor/composer/installed.php (modified) (2 diffs)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/CHANGELOG.TXT (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/LICENSE.TXT (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/composer.json (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/courier.php (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/courierb.php (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/courierbi.php (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/courieri.php (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfacourier.php (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfacourier.z (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfacourierb.php (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfacourierb.z (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfacourierbi.php (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfacourierbi.z (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfacourieri.php (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfacourieri.z (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfatimes.php (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfatimes.z (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfatimesb.php (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfatimesb.z (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfatimesbi.php (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfatimesbi.z (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfatimesi.php (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/pdfatimesi.z (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/times.php (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/timesb.php (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/timesbi.php (deleted)
-
tags/3.1.8/vendor/tecnickcom/tcpdf/fonts/timesi.php (deleted)
-
trunk/la-terreta-food-labels-for-woocommerce.php (modified) (9 diffs)
-
trunk/lib/design.php (modified) (1 diff)
-
trunk/lib/functions.php (modified) (2 diffs)
-
trunk/lib/menu.php (modified) (5 diffs)
-
trunk/readme.txt (modified) (4 diffs)
-
trunk/vendor/composer/installed.php (modified) (2 diffs)
-
trunk/vendor/tecnickcom/tcpdf/CHANGELOG.TXT (deleted)
-
trunk/vendor/tecnickcom/tcpdf/LICENSE.TXT (deleted)
-
trunk/vendor/tecnickcom/tcpdf/composer.json (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/courier.php (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/courierb.php (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/courierbi.php (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/courieri.php (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfacourier.php (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfacourier.z (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfacourierb.php (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfacourierb.z (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfacourierbi.php (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfacourierbi.z (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfacourieri.php (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfacourieri.z (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfatimes.php (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfatimes.z (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfatimesb.php (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfatimesb.z (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfatimesbi.php (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfatimesbi.z (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfatimesi.php (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/pdfatimesi.z (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/times.php (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/timesb.php (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/timesbi.php (deleted)
-
trunk/vendor/tecnickcom/tcpdf/fonts/timesi.php (deleted)
Legend:
- Unmodified
- Added
- Removed
-
la-terreta-food-labels-for-woocommerce/tags/3.1.8/la-terreta-food-labels-for-woocommerce.php
r3595095 r3675014 4 4 * Plugin URI: https://www.laterretagames.com/imprimir-etiquetas-productos-premium-plugin-woocommerce/ 5 5 * Description: Generate PDF labels for WooCommerce products with food information. Compliance with Regulation (EC) No 1169/2011 (food information to consumers). 6 * Version: 3.1. 76 * Version: 3.1.8 7 7 * Author: La Terreta Games 8 8 * Author URI: https://laterretagames.com … … 23 23 } 24 24 25 define('IETIQ_FREE_VERSION', '3.1. 7');25 define('IETIQ_FREE_VERSION', '3.1.8'); 26 26 define('IETIQ_FREE_PLUGIN_DIR', plugin_dir_path(__FILE__)); 27 27 define('IETIQ_FREE_PLUGIN_URL', plugin_dir_url(__FILE__)); … … 124 124 } 125 125 add_filter('plugin_action_links_' . IETIQ_FREE_PLUGIN_BASENAME, 'ietiq_free_plugin_action_links'); 126 127 /** 128 * Enlaces adicionales bajo la descripción del plugin en la lista de plugins 129 * (Documentación | Soporte | Valorar | Premium) 130 */ 131 function ietiq_free_plugin_row_meta( $links, $file ) { 132 if ( IETIQ_FREE_PLUGIN_BASENAME !== $file ) { 133 return $links; 134 } 135 136 $row_meta = array( 137 'docs' => '<a href="https://wordpress.org/plugins/la-terreta-food-labels-for-woocommerce/#faq" target="_blank">' . esc_html__( 'Documentation', 'la-terreta-food-labels-for-woocommerce' ) . '</a>', 138 'support' => '<a href="https://wordpress.org/support/plugin/la-terreta-food-labels-for-woocommerce/" target="_blank">' . esc_html__( 'Support', 'la-terreta-food-labels-for-woocommerce' ) . '</a>', 139 'review' => '<a href="https://wordpress.org/support/plugin/la-terreta-food-labels-for-woocommerce/reviews/#new-post" target="_blank">' . esc_html__( '⭐ Rate this plugin', 'la-terreta-food-labels-for-woocommerce' ) . '</a>', 140 'premium' => '<a href="https://www.laterretagames.com/imprimir-etiquetas-productos-premium-plugin-woocommerce/" target="_blank" style="color:#f39c12;font-weight:bold;">' . esc_html__( 'Get Premium', 'la-terreta-food-labels-for-woocommerce' ) . '</a>', 141 ); 142 143 return array_merge( $links, $row_meta ); 144 } 145 add_filter( 'plugin_row_meta', 'ietiq_free_plugin_row_meta', 10, 2 ); 126 146 127 147 /** … … 278 298 279 299 /** 300 * Aviso de "logro" por volumen de uso real (25/100/250/500/1000 etiquetas). 301 * Usa el dato real de uso del propio usuario en vez de un mensaje genérico 302 * — más persuasivo porque encaja con lo que esa tienda ya está haciendo. 303 */ 304 function ietiq_free_milestone_notice() { 305 if ( ! current_user_can( 'manage_options' ) ) return; 306 307 $screen = get_current_screen(); 308 if ( ! $screen ) return; 309 310 $allowed_screens = [ 'edit-shop_order', 'shop_order', 'woocommerce_page_wc-orders', 'plugins', 'dashboard' ]; 311 $is_plugin_screen = strpos( $screen->id, 'ietiq_ajustes' ) !== false; 312 if ( ! $is_plugin_screen && ! in_array( $screen->id, $allowed_screens, true ) ) return; 313 314 $count = (int) get_option( 'ietiq_pdf_generated_count', 0 ); 315 $milestones = array( 25, 100, 250, 500, 1000 ); 316 317 $milestone = 0; 318 foreach ( $milestones as $m ) { 319 if ( $count >= $m ) { 320 $milestone = $m; 321 } 322 } 323 if ( ! $milestone ) return; 324 325 $user_id = get_current_user_id(); 326 $seen_meta = (int) get_user_meta( $user_id, 'ietiq_milestone_seen', true ); 327 if ( $seen_meta >= $milestone ) return; 328 329 $snooze_until = (int) get_user_meta( $user_id, 'ietiq_milestone_snooze_until', true ); 330 if ( $snooze_until && time() < $snooze_until ) return; 331 332 $upgrade_url = 'https://www.laterretagames.com/imprimir-etiquetas-productos-premium-plugin-woocommerce/'; 333 $nonce = wp_create_nonce( 'ietiq_milestone_action' ); 334 $dismiss_url = add_query_arg( [ 'ietiq_milestone_action' => 'dismiss', 'ietiq_milestone_value' => $milestone, '_ietiq_milestone_nonce' => $nonce ] ); 335 $later_url = add_query_arg( [ 'ietiq_milestone_action' => 'later', '_ietiq_milestone_nonce' => $nonce ] ); 336 ?> 337 <div class="notice notice-info" style="border-left: 4px solid #00a32a; padding: 12px 15px;"> 338 <p style="margin: 0 0 8px 0; font-size: 14px;"> 339 <strong> 340 <?php 341 printf( 342 /* translators: %s: number of labels printed, formatted */ 343 esc_html__( '🎉 You\'ve printed %s labels with Print Product Labels FREE!', 'la-terreta-food-labels-for-woocommerce' ), 344 esc_html( number_format_i18n( $count ) ) 345 ); 346 ?> 347 </strong><br> 348 <?php esc_html_e( 'Premium adds QR codes, shipping labels and removes limits — built for stores at your volume.', 'la-terreta-food-labels-for-woocommerce' ); ?> 349 </p> 350 <p style="margin: 0;"> 351 <a href="<?php echo esc_url( $upgrade_url ); ?>" target="_blank" class="button button-primary" style="margin-right: 8px;"> 352 <?php esc_html_e( '🚀 See Premium →', 'la-terreta-food-labels-for-woocommerce' ); ?> 353 </a> 354 <a href="<?php echo esc_url( $dismiss_url ); ?>" style="margin-right: 12px;"> 355 <?php esc_html_e( 'Dismiss', 'la-terreta-food-labels-for-woocommerce' ); ?> 356 </a> 357 <a href="<?php echo esc_url( $later_url ); ?>"> 358 <?php esc_html_e( 'Remind me later', 'la-terreta-food-labels-for-woocommerce' ); ?> 359 </a> 360 </p> 361 </div> 362 <?php 363 } 364 add_action( 'admin_notices', 'ietiq_free_milestone_notice' ); 365 366 /** 367 * Gestionar las acciones del aviso de logro (descartar / posponer) 368 */ 369 function ietiq_free_handle_milestone_action() { 370 if ( ! isset( $_GET['ietiq_milestone_action'], $_GET['_ietiq_milestone_nonce'] ) ) return; 371 if ( ! wp_verify_nonce( sanitize_key( $_GET['_ietiq_milestone_nonce'] ), 'ietiq_milestone_action' ) ) return; 372 if ( ! is_user_logged_in() ) return; 373 374 $user_id = get_current_user_id(); 375 $action = sanitize_key( $_GET['ietiq_milestone_action'] ); 376 377 if ( 'dismiss' === $action ) { 378 $value = isset( $_GET['ietiq_milestone_value'] ) ? absint( $_GET['ietiq_milestone_value'] ) : 0; 379 if ( $value ) { 380 update_user_meta( $user_id, 'ietiq_milestone_seen', $value ); 381 } 382 } elseif ( 'later' === $action ) { 383 update_user_meta( $user_id, 'ietiq_milestone_snooze_until', time() + 3 * DAY_IN_SECONDS ); 384 } 385 386 wp_safe_redirect( remove_query_arg( [ 'ietiq_milestone_action', 'ietiq_milestone_value', '_ietiq_milestone_nonce' ] ) ); 387 exit; 388 } 389 add_action( 'admin_init', 'ietiq_free_handle_milestone_action' ); 390 391 /** 280 392 * Ocultar la pestaña "Información adicional" de WooCommerce 281 393 */ … … 320 432 $nonce = wp_create_nonce( 'ietiq_welcome_action' ); 321 433 $dismiss_url = add_query_arg( [ 'ietiq_welcome_action' => 'dismiss', '_ietiq_welcome_nonce' => $nonce ] ); 434 $optin_url = add_query_arg( [ 'ietiq_welcome_action' => 'optin', '_ietiq_welcome_nonce' => $nonce ] ); 435 $already_optin = get_user_meta( $user_id, 'ietiq_marketing_optin', true ); 322 436 ?> 323 437 <div class="notice notice-success" style="border-left: 4px solid #00a32a; padding: 16px 20px;"> … … 344 458 </li> 345 459 </ol> 346 <p style="margin: 0 ;">460 <p style="margin: 0 0 10px 0;"> 347 461 <a href="<?php echo esc_url( $settings_url ); ?>" class="button button-primary" style="margin-right: 10px;"> 348 462 <?php esc_html_e( 'Go to Settings →', 'la-terreta-food-labels-for-woocommerce' ); ?> … … 352 466 </a> 353 467 </p> 468 <?php if ( ! $already_optin ) : ?> 469 <p style="margin: 0; padding-top: 10px; border-top: 1px solid #e2e2e2; color: #666; font-size: 13px;"> 470 📩 <?php esc_html_e( 'Want occasional tips on food label compliance (CE 1169/2011)? No spam, unsubscribe anytime.', 'la-terreta-food-labels-for-woocommerce' ); ?> 471 <a href="<?php echo esc_url( $optin_url ); ?>" style="font-weight: bold;"> 472 <?php esc_html_e( 'Yes, send me tips →', 'la-terreta-food-labels-for-woocommerce' ); ?> 473 </a> 474 </p> 475 <?php endif; ?> 354 476 </div> 355 477 <?php … … 365 487 if ( ! is_user_logged_in() ) return; 366 488 367 if ( 'dismiss' === sanitize_key( $_GET['ietiq_welcome_action'] ) ) { 489 $action = sanitize_key( $_GET['ietiq_welcome_action'] ); 490 491 if ( 'dismiss' === $action ) { 492 update_user_meta( get_current_user_id(), 'ietiq_welcome_dismissed', 1 ); 493 } elseif ( 'optin' === $action && current_user_can( 'manage_options' ) ) { 494 ietiq_free_record_marketing_optin( get_current_user_id() ); 368 495 update_user_meta( get_current_user_id(), 'ietiq_welcome_dismissed', 1 ); 369 496 } … … 372 499 exit; 373 500 } 501 502 /** 503 * Registra el opt-in de marketing usando el email de la cuenta de admin 504 * actual. Se guarda ÚNICAMENTE en la base de datos local de WordPress 505 * (wp_options), sin ninguna llamada a servicios externos — coherente con 506 * la política de privacidad del readme ("no collect or store any personal 507 * data outside your own WordPress database"). Conectarlo a una 508 * herramienta de email marketing real (Mailchimp, ConvertKit...) requiere 509 * un paso aparte y, si se añade, declarar el servicio externo en el 510 * readme.txt (regla de WP.org). 511 */ 512 function ietiq_free_record_marketing_optin( $user_id ) { 513 update_user_meta( $user_id, 'ietiq_marketing_optin', time() ); 514 515 $user = get_userdata( $user_id ); 516 if ( ! $user || empty( $user->user_email ) ) { 517 return; 518 } 519 520 $optins = get_option( 'ietiq_marketing_optins', array() ); 521 if ( ! is_array( $optins ) ) { 522 $optins = array(); 523 } 524 525 foreach ( $optins as $entry ) { 526 if ( isset( $entry['email'] ) && $entry['email'] === $user->user_email ) { 527 return; // ya registrado 528 } 529 } 530 531 $optins[] = array( 532 'email' => $user->user_email, 533 'date' => current_time( 'mysql' ), 534 'site' => home_url(), 535 ); 536 537 update_option( 'ietiq_marketing_optins', $optins, false ); 538 } 539 540 /** 541 * Exportar los opt-ins de marketing a CSV (uso manual del administrador, 542 * ninguna llamada automática a servicios externos) 543 */ 544 function ietiq_free_export_marketing_optins() { 545 if ( ! current_user_can( 'manage_options' ) ) { 546 wp_die( esc_html__( 'Insufficient permissions.', 'la-terreta-food-labels-for-woocommerce' ) ); 547 } 548 check_admin_referer( 'ietiq_export_optins' ); 549 550 $optins = get_option( 'ietiq_marketing_optins', array() ); 551 if ( ! is_array( $optins ) ) { 552 $optins = array(); 553 } 554 555 nocache_headers(); 556 header( 'Content-Type: text/csv; charset=utf-8' ); 557 header( 'Content-Disposition: attachment; filename=ietiq-marketing-optins.csv' ); 558 559 $out = fopen( 'php://output', 'w' ); 560 fputcsv( $out, array( 'email', 'date', 'site' ) ); 561 foreach ( $optins as $entry ) { 562 fputcsv( $out, array( 563 isset( $entry['email'] ) ? $entry['email'] : '', 564 isset( $entry['date'] ) ? $entry['date'] : '', 565 isset( $entry['site'] ) ? $entry['site'] : '', 566 ) ); 567 } 568 fclose( $out ); 569 exit; 570 } 571 add_action( 'admin_post_ietiq_export_marketing_optins', 'ietiq_free_export_marketing_optins' ); 572 573 /** 574 * Mostrar el contador de opt-ins y el enlace de descarga CSV al final de 575 * la página de ajustes 576 */ 577 function ietiq_free_render_marketing_optins_box() { 578 if ( ! current_user_can( 'manage_options' ) ) return; 579 580 $optins = get_option( 'ietiq_marketing_optins', array() ); 581 if ( ! is_array( $optins ) || empty( $optins ) ) return; 582 583 $export_url = wp_nonce_url( admin_url( 'admin-post.php?action=ietiq_export_marketing_optins' ), 'ietiq_export_optins' ); 584 ?> 585 <hr style="margin: 30px 0 20px;" /> 586 <h2><?php esc_html_e( 'Email tips subscribers', 'la-terreta-food-labels-for-woocommerce' ); ?></h2> 587 <p> 588 <?php 589 printf( 590 /* translators: %d: number of subscribers */ 591 esc_html( _n( '%d admin opted in to receive occasional compliance tips.', '%d admins opted in to receive occasional compliance tips.', count( $optins ), 'la-terreta-food-labels-for-woocommerce' ) ), 592 count( $optins ) 593 ); 594 ?> 595 <a href="<?php echo esc_url( $export_url ); ?>" class="button"><?php esc_html_e( 'Download CSV', 'la-terreta-food-labels-for-woocommerce' ); ?></a> 596 </p> 597 <p class="description"><?php esc_html_e( 'Stored locally in your WordPress database only — nothing is sent anywhere automatically.', 'la-terreta-food-labels-for-woocommerce' ); ?></p> 598 <?php 599 } 600 add_action( 'ietiq_after_settings_page', 'ietiq_free_render_marketing_optins_box' ); 374 601 add_action( 'admin_init', 'ietiq_free_handle_welcome_action' ); 602 603 /** 604 * Encuesta de desactivación: antes de desactivar preguntamos el motivo 605 * (opcional, se puede saltar sin rellenar nada) y, si el motivo es que 606 * falta una función, mostramos un aviso de que está en Premium. El motivo 607 * se guarda solo localmente (wp_options), nunca se envía a ningún sitio. 608 */ 609 function ietiq_free_deactivation_survey_assets( $hook ) { 610 if ( 'plugins.php' !== $hook ) { 611 return; 612 } 613 614 $reasons = array( 615 'missing_feature' => __( 'Missing a feature I need (QR codes, shipping labels, unlimited products...)', 'la-terreta-food-labels-for-woocommerce' ), 616 'too_complex' => __( 'Too complex or hard to set up', 'la-terreta-food-labels-for-woocommerce' ), 617 'found_bug' => __( 'Found a bug', 'la-terreta-food-labels-for-woocommerce' ), 618 'switched' => __( 'Switched to another plugin', 'la-terreta-food-labels-for-woocommerce' ), 619 'temporary' => __( 'Temporary deactivation, I will reactivate', 'la-terreta-food-labels-for-woocommerce' ), 620 'other' => __( 'Other', 'la-terreta-food-labels-for-woocommerce' ), 621 ); 622 623 ?> 624 <div id="ietiq-deactivate-modal" style="display:none;position:fixed;inset:0;z-index:100000;background:rgba(0,0,0,0.5);"> 625 <div style="background:#fff;max-width:480px;margin:10vh auto;padding:24px;border-radius:4px;box-shadow:0 4px 20px rgba(0,0,0,0.2);"> 626 <h2 style="margin-top:0;"><?php esc_html_e( 'Quick question before you go', 'la-terreta-food-labels-for-woocommerce' ); ?></h2> 627 <p><?php esc_html_e( 'What made you deactivate Print Product Labels? (optional, helps us improve)', 'la-terreta-food-labels-for-woocommerce' ); ?></p> 628 <p> 629 <?php foreach ( $reasons as $key => $label ) : ?> 630 <label style="display:block;margin-bottom:6px;"> 631 <input type="radio" name="ietiq_deactivate_reason" value="<?php echo esc_attr( $key ); ?>" /> 632 <?php echo esc_html( $label ); ?> 633 </label> 634 <?php endforeach; ?> 635 </p> 636 <p id="ietiq-deactivate-premium-note" style="display:none;background:#fff8e5;border-left:4px solid #f39c12;padding:10px 12px;margin:10px 0;"> 637 <?php esc_html_e( 'Good news: that\'s exactly what Premium adds.', 'la-terreta-food-labels-for-woocommerce' ); ?> 638 <a href="https://www.laterretagames.com/imprimir-etiquetas-productos-premium-plugin-woocommerce/" target="_blank" style="font-weight:bold;"> 639 <?php esc_html_e( 'See Premium →', 'la-terreta-food-labels-for-woocommerce' ); ?> 640 </a> 641 </p> 642 <textarea id="ietiq-deactivate-note" placeholder="<?php esc_attr_e( 'Anything else? (optional)', 'la-terreta-food-labels-for-woocommerce' ); ?>" style="width:100%;height:60px;margin-bottom:14px;"></textarea> 643 <p style="text-align:right;margin-bottom:0;"> 644 <button type="button" class="button" id="ietiq-deactivate-skip"><?php esc_html_e( 'Skip & Deactivate', 'la-terreta-food-labels-for-woocommerce' ); ?></button> 645 <button type="button" class="button button-primary" id="ietiq-deactivate-submit"><?php esc_html_e( 'Submit & Deactivate', 'la-terreta-food-labels-for-woocommerce' ); ?></button> 646 </p> 647 </div> 648 </div> 649 <?php 650 $ajax_url = admin_url( 'admin-ajax.php' ); 651 $nonce = wp_create_nonce( 'ietiq_deactivation_feedback' ); 652 $basename = esc_js( IETIQ_FREE_PLUGIN_BASENAME ); 653 ?> 654 <script> 655 jQuery(function ($) { 656 var row = $('tr[data-plugin="<?php echo $basename; ?>"]'); 657 var deactivateLink = row.find('.deactivate a'); 658 if (!deactivateLink.length) { return; } 659 660 var targetUrl = deactivateLink.attr('href'); 661 var modal = $('#ietiq-deactivate-modal'); 662 var premiumNote = $('#ietiq-deactivate-premium-note'); 663 664 deactivateLink.on('click', function (e) { 665 e.preventDefault(); 666 modal.show(); 667 }); 668 669 $('input[name="ietiq_deactivate_reason"]').on('change', function () { 670 premiumNote.toggle($(this).val() === 'missing_feature'); 671 }); 672 673 modal.on('click', function (e) { 674 if (e.target === this) { modal.hide(); } 675 }); 676 677 $('#ietiq-deactivate-skip').on('click', function () { 678 window.location.href = targetUrl; 679 }); 680 681 $('#ietiq-deactivate-submit').on('click', function () { 682 var reason = $('input[name="ietiq_deactivate_reason"]:checked').val() || ''; 683 var note = $('#ietiq-deactivate-note').val() || ''; 684 var btn = $(this); 685 btn.prop('disabled', true); 686 687 $.post('<?php echo esc_url_raw( $ajax_url ); ?>', { 688 action: 'ietiq_free_deactivation_feedback', 689 nonce: '<?php echo esc_js( $nonce ); ?>', 690 reason: reason, 691 note: note 692 }).always(function () { 693 window.location.href = targetUrl; 694 }); 695 }); 696 }); 697 </script> 698 <?php 699 } 700 add_action( 'admin_footer', 'ietiq_free_deactivation_survey_assets' ); 701 702 /** 703 * Guarda el motivo de desactivación — solo localmente (wp_options), sin 704 * ninguna llamada a servicios externos. 705 */ 706 function ietiq_free_handle_deactivation_feedback() { 707 check_ajax_referer( 'ietiq_deactivation_feedback', 'nonce' ); 708 709 if ( ! current_user_can( 'activate_plugins' ) ) { 710 wp_send_json_error(); 711 } 712 713 $allowed_reasons = array( 'missing_feature', 'too_complex', 'found_bug', 'switched', 'temporary', 'other' ); 714 $reason = isset( $_POST['reason'] ) ? sanitize_key( wp_unslash( $_POST['reason'] ) ) : ''; 715 if ( ! in_array( $reason, $allowed_reasons, true ) ) { 716 $reason = ''; 717 } 718 $note = isset( $_POST['note'] ) ? sanitize_textarea_field( wp_unslash( $_POST['note'] ) ) : ''; 719 720 if ( $reason || $note ) { 721 $feedback = get_option( 'ietiq_deactivation_feedback', array() ); 722 if ( ! is_array( $feedback ) ) { 723 $feedback = array(); 724 } 725 $feedback[] = array( 726 'reason' => $reason, 727 'note' => $note, 728 'date' => current_time( 'mysql' ), 729 ); 730 update_option( 'ietiq_deactivation_feedback', $feedback, false ); 731 } 732 733 wp_send_json_success(); 734 } 735 add_action( 'wp_ajax_ietiq_free_deactivation_feedback', 'ietiq_free_handle_deactivation_feedback' ); 375 736 376 737 add_action('before_woocommerce_init', function() { -
la-terreta-food-labels-for-woocommerce/tags/3.1.8/lib/design.php
r3545025 r3675014 550 550 </ul> 551 551 </p> 552 <p class="form-field" style="color:#666;font-size:12px;"> 553 🚀 <?php 554 printf( 555 /* translators: %s: link to the Premium page */ 556 esc_html__( 'Premium adds per-variation net weight, conservation/consumption method and QR code. %s', 'la-terreta-food-labels-for-woocommerce' ), 557 '<a href="https://www.laterretagames.com/imprimir-etiquetas-productos-premium-plugin-woocommerce/" target="_blank" style="font-weight:bold;">' . esc_html__( 'See Premium →', 'la-terreta-food-labels-for-woocommerce' ) . '</a>' 558 ); 559 ?> 560 </p> 552 561 </div> 553 562 <?php -
la-terreta-food-labels-for-woocommerce/tags/3.1.8/lib/functions.php
r3595095 r3675014 249 249 $etiquetasPagina = 5; 250 250 251 // Cargar logo una sola vez antes del bucle252 $logo_id = (int) get_option('ietiq_company_logo_id', 0);253 $logo_path = '';254 if ($logo_id) {255 $logo_file = get_attached_file($logo_id);256 if ($logo_file && file_exists($logo_file)) {257 $logo_path = $logo_file;258 }259 }260 261 251 $items = $order->get_items(); 262 252 … … 400 390 $pdf->Rect($marginLeft, $Y, $pdf->getPageWidth() - 40, 45, 'D', array('all' => $style)); 401 391 402 // Logo de empresa — esquina superior derecha de la etiqueta403 if ($logo_path) {404 $logo_x = $marginLeft + ($pdf->getPageWidth() - 40) - 38;405 try {406 $pdf->Image($logo_path, $logo_x, $Y + 2, 35, 14, '', '', '', true, 150, '', false, false, 0, 'C');407 } catch (Exception $e) {408 // No se puede renderizar el logo, continuar sin él409 }410 }411 412 392 $pdf->Ln(10); 413 393 $item_counter++; -
la-terreta-food-labels-for-woocommerce/tags/3.1.8/lib/menu.php
r3595095 r3675014 57 57 register_setting('ietiq_datos_grupo', 'ietiq_provincia', array('sanitize_callback' => 'sanitize_text_field')); 58 58 register_setting('ietiq_datos_grupo', 'ietiq_pais', array('sanitize_callback' => 'sanitize_text_field')); 59 register_setting('ietiq_datos_grupo', 'ietiq_company_logo_id', array('sanitize_callback' => 'absint'));60 59 61 60 // Añadir sección … … 84 83 add_settings_field('ietiq_pais', __('Country', 'la-terreta-food-labels-for-woocommerce'), 85 84 'ietiq_campo_pais', 'ietiq_datos', 'ietiq_datos_seccion'); 86 87 add_settings_field('ietiq_company_logo_id', __('Company Logo', 'la-terreta-food-labels-for-woocommerce'),88 'ietiq_campo_company_logo', 'ietiq_datos', 'ietiq_datos_seccion');89 85 } 90 86 … … 262 258 echo '<input type="checkbox" name="ietiq_mostrarMeta" value="1" ' . checked(1, $mostrarMeta, false) . ' />'; 263 259 } 264 265 function ietiq_campo_company_logo() {266 $logo_id = (int) get_option('ietiq_company_logo_id', 0);267 $logo_url = $logo_id ? wp_get_attachment_image_url($logo_id, array(300, 100)) : '';268 $has_logo = ! empty($logo_url);269 ?>270 <div id="ietiq-logo-container">271 <img272 id="ietiq-logo-preview"273 src="<?php echo $has_logo ? esc_url($logo_url) : ''; ?>"274 alt=""275 style="max-width:220px;max-height:80px;display:<?php echo $has_logo ? 'block' : 'none'; ?>;margin-bottom:8px;border:1px solid #ddd;padding:6px;background:#fff;"276 />277 <input type="hidden" id="ietiq_company_logo_id" name="ietiq_company_logo_id" value="<?php echo esc_attr($logo_id ?: ''); ?>" />278 <button type="button" id="ietiq-upload-logo" class="button">279 <?php esc_html_e('Select Logo', 'la-terreta-food-labels-for-woocommerce'); ?>280 </button>281 <button type="button" id="ietiq-remove-logo" class="button" style="margin-left:8px;<?php echo $has_logo ? '' : 'display:none;'; ?>">282 <?php esc_html_e('Remove', 'la-terreta-food-labels-for-woocommerce'); ?>283 </button>284 <p class="description" style="margin-top:8px;">285 <?php esc_html_e('Logo appears in the top-right corner of each product label. PNG with transparent background recommended (min. 300 px wide).', 'la-terreta-food-labels-for-woocommerce'); ?>286 </p>287 </div>288 <?php289 }290 291 /**292 * Encolar media library en la página Company Information293 */294 function ietiq_free_enqueue_logo_scripts($hook) {295 if ('ietiq_ajustes_page_ietiq_datos' !== $hook) {296 return;297 }298 wp_enqueue_media();299 $title = esc_js(__('Select Company Logo', 'la-terreta-food-labels-for-woocommerce'));300 $use = esc_js(__('Use this image', 'la-terreta-food-labels-for-woocommerce'));301 $js = "302 jQuery(function(jq) {303 var mediaFrame;304 jq('#ietiq-upload-logo').on('click', function(e) {305 e.preventDefault();306 if (mediaFrame) { mediaFrame.open(); return; }307 mediaFrame = wp.media({308 title: '{$title}',309 button: { text: '{$use}' },310 multiple: false,311 library: { type: 'image' }312 });313 mediaFrame.on('select', function() {314 var att = mediaFrame.state().get('selection').first().toJSON();315 jq('#ietiq_company_logo_id').val(att.id);316 jq('#ietiq-logo-preview').attr('src', att.url).show();317 jq('#ietiq-remove-logo').show();318 });319 mediaFrame.open();320 });321 jq('#ietiq-remove-logo').on('click', function(e) {322 e.preventDefault();323 jq('#ietiq_company_logo_id').val('');324 jq('#ietiq-logo-preview').attr('src', '').hide();325 jq(this).hide();326 });327 });328 ";329 wp_add_inline_script('jquery', $js);330 }331 add_action('admin_enqueue_scripts', 'ietiq_free_enqueue_logo_scripts');332 260 333 261 /****************** PÁGINAS DE AJUSTES **********************/ … … 347 275 ?> 348 276 </form> 277 278 <?php do_action('ietiq_after_settings_page'); ?> 349 279 </div> 350 280 <?php … … 365 295 ?> 366 296 </form> 297 <p class="description"> 298 🚀 <?php 299 printf( 300 /* translators: %s: link to the Premium page */ 301 esc_html__( 'Want your logo printed on every label? That\'s a %s feature.', 'la-terreta-food-labels-for-woocommerce' ), 302 '<a href="https://www.laterretagames.com/imprimir-etiquetas-productos-premium-plugin-woocommerce/" target="_blank" style="font-weight:bold;">' . esc_html__( 'Premium', 'la-terreta-food-labels-for-woocommerce' ) . '</a>' 303 ); 304 ?> 305 </p> 367 306 </div> 368 307 <?php -
la-terreta-food-labels-for-woocommerce/tags/3.1.8/readme.txt
r3595095 r3675014 5 5 Requires at least: 5.8 6 6 Tested up to: 6.9 7 Stable tag: 3.1. 77 Stable tag: 3.1.8 8 8 Requires PHP: 7.4 9 9 License: GPLv2 or later … … 43 43 * ✅ Company data on every label 44 44 * ✅ Available in 4 languages: English, Spanish, French, German 45 * ✅ Company logo on every label (upload in Company Information settings)46 45 * ✅ Works with WooCommerce HPOS (High-Performance Order Storage) 47 46 … … 50 49 Upgrade to **Premium** to cover the full EU Regulation 1169/2011 and save time with professional tools: 51 50 51 * ✨ **Company logo** printed on every label 52 52 * ✨ **Net weight** on the label (required for pre-packaged foods) 53 53 * ✨ **Conservation & consumption instructions** … … 147 147 == Changelog == 148 148 149 = 3.1.8 = 150 * Added Documentation/Support/Rate/Premium links under the plugin name on the Plugins screen 151 * Added optional "send me tips" opt-in in the welcome notice (stored locally only, never sent anywhere automatically) 152 * Added a usage-milestone notice (25/100/250/500/1000 labels printed) pointing to Premium 153 * Added a contextual Premium note on the "Ingredients" tab of product variations 154 * Added a deactivation feedback survey with an optional link to Premium 155 149 156 = 3.1.7 = 150 * Added company logo on product labels (upload PNG/JPG in Company Information settings, appears top-right of each label)157 * Minor fixes 151 158 152 159 = 3.1.6 = -
la-terreta-food-labels-for-woocommerce/tags/3.1.8/vendor/composer/installed.php
r3545025 r3675014 4 4 'pretty_version' => 'dev-main', 5 5 'version' => 'dev-main', 6 'reference' => ' c98f78e21b3590ada393add8ba390939d20656de',6 'reference' => '3ea9113eb151d022085cd81c44060fbf742be4fe', 7 7 'type' => 'wordpress-plugin', 8 8 'install_path' => __DIR__ . '/../../', … … 14 14 'pretty_version' => 'dev-main', 15 15 'version' => 'dev-main', 16 'reference' => ' c98f78e21b3590ada393add8ba390939d20656de',16 'reference' => '3ea9113eb151d022085cd81c44060fbf742be4fe', 17 17 'type' => 'wordpress-plugin', 18 18 'install_path' => __DIR__ . '/../../', -
la-terreta-food-labels-for-woocommerce/trunk/la-terreta-food-labels-for-woocommerce.php
r3595095 r3675014 4 4 * Plugin URI: https://www.laterretagames.com/imprimir-etiquetas-productos-premium-plugin-woocommerce/ 5 5 * Description: Generate PDF labels for WooCommerce products with food information. Compliance with Regulation (EC) No 1169/2011 (food information to consumers). 6 * Version: 3.1. 76 * Version: 3.1.8 7 7 * Author: La Terreta Games 8 8 * Author URI: https://laterretagames.com … … 23 23 } 24 24 25 define('IETIQ_FREE_VERSION', '3.1. 7');25 define('IETIQ_FREE_VERSION', '3.1.8'); 26 26 define('IETIQ_FREE_PLUGIN_DIR', plugin_dir_path(__FILE__)); 27 27 define('IETIQ_FREE_PLUGIN_URL', plugin_dir_url(__FILE__)); … … 124 124 } 125 125 add_filter('plugin_action_links_' . IETIQ_FREE_PLUGIN_BASENAME, 'ietiq_free_plugin_action_links'); 126 127 /** 128 * Enlaces adicionales bajo la descripción del plugin en la lista de plugins 129 * (Documentación | Soporte | Valorar | Premium) 130 */ 131 function ietiq_free_plugin_row_meta( $links, $file ) { 132 if ( IETIQ_FREE_PLUGIN_BASENAME !== $file ) { 133 return $links; 134 } 135 136 $row_meta = array( 137 'docs' => '<a href="https://wordpress.org/plugins/la-terreta-food-labels-for-woocommerce/#faq" target="_blank">' . esc_html__( 'Documentation', 'la-terreta-food-labels-for-woocommerce' ) . '</a>', 138 'support' => '<a href="https://wordpress.org/support/plugin/la-terreta-food-labels-for-woocommerce/" target="_blank">' . esc_html__( 'Support', 'la-terreta-food-labels-for-woocommerce' ) . '</a>', 139 'review' => '<a href="https://wordpress.org/support/plugin/la-terreta-food-labels-for-woocommerce/reviews/#new-post" target="_blank">' . esc_html__( '⭐ Rate this plugin', 'la-terreta-food-labels-for-woocommerce' ) . '</a>', 140 'premium' => '<a href="https://www.laterretagames.com/imprimir-etiquetas-productos-premium-plugin-woocommerce/" target="_blank" style="color:#f39c12;font-weight:bold;">' . esc_html__( 'Get Premium', 'la-terreta-food-labels-for-woocommerce' ) . '</a>', 141 ); 142 143 return array_merge( $links, $row_meta ); 144 } 145 add_filter( 'plugin_row_meta', 'ietiq_free_plugin_row_meta', 10, 2 ); 126 146 127 147 /** … … 278 298 279 299 /** 300 * Aviso de "logro" por volumen de uso real (25/100/250/500/1000 etiquetas). 301 * Usa el dato real de uso del propio usuario en vez de un mensaje genérico 302 * — más persuasivo porque encaja con lo que esa tienda ya está haciendo. 303 */ 304 function ietiq_free_milestone_notice() { 305 if ( ! current_user_can( 'manage_options' ) ) return; 306 307 $screen = get_current_screen(); 308 if ( ! $screen ) return; 309 310 $allowed_screens = [ 'edit-shop_order', 'shop_order', 'woocommerce_page_wc-orders', 'plugins', 'dashboard' ]; 311 $is_plugin_screen = strpos( $screen->id, 'ietiq_ajustes' ) !== false; 312 if ( ! $is_plugin_screen && ! in_array( $screen->id, $allowed_screens, true ) ) return; 313 314 $count = (int) get_option( 'ietiq_pdf_generated_count', 0 ); 315 $milestones = array( 25, 100, 250, 500, 1000 ); 316 317 $milestone = 0; 318 foreach ( $milestones as $m ) { 319 if ( $count >= $m ) { 320 $milestone = $m; 321 } 322 } 323 if ( ! $milestone ) return; 324 325 $user_id = get_current_user_id(); 326 $seen_meta = (int) get_user_meta( $user_id, 'ietiq_milestone_seen', true ); 327 if ( $seen_meta >= $milestone ) return; 328 329 $snooze_until = (int) get_user_meta( $user_id, 'ietiq_milestone_snooze_until', true ); 330 if ( $snooze_until && time() < $snooze_until ) return; 331 332 $upgrade_url = 'https://www.laterretagames.com/imprimir-etiquetas-productos-premium-plugin-woocommerce/'; 333 $nonce = wp_create_nonce( 'ietiq_milestone_action' ); 334 $dismiss_url = add_query_arg( [ 'ietiq_milestone_action' => 'dismiss', 'ietiq_milestone_value' => $milestone, '_ietiq_milestone_nonce' => $nonce ] ); 335 $later_url = add_query_arg( [ 'ietiq_milestone_action' => 'later', '_ietiq_milestone_nonce' => $nonce ] ); 336 ?> 337 <div class="notice notice-info" style="border-left: 4px solid #00a32a; padding: 12px 15px;"> 338 <p style="margin: 0 0 8px 0; font-size: 14px;"> 339 <strong> 340 <?php 341 printf( 342 /* translators: %s: number of labels printed, formatted */ 343 esc_html__( '🎉 You\'ve printed %s labels with Print Product Labels FREE!', 'la-terreta-food-labels-for-woocommerce' ), 344 esc_html( number_format_i18n( $count ) ) 345 ); 346 ?> 347 </strong><br> 348 <?php esc_html_e( 'Premium adds QR codes, shipping labels and removes limits — built for stores at your volume.', 'la-terreta-food-labels-for-woocommerce' ); ?> 349 </p> 350 <p style="margin: 0;"> 351 <a href="<?php echo esc_url( $upgrade_url ); ?>" target="_blank" class="button button-primary" style="margin-right: 8px;"> 352 <?php esc_html_e( '🚀 See Premium →', 'la-terreta-food-labels-for-woocommerce' ); ?> 353 </a> 354 <a href="<?php echo esc_url( $dismiss_url ); ?>" style="margin-right: 12px;"> 355 <?php esc_html_e( 'Dismiss', 'la-terreta-food-labels-for-woocommerce' ); ?> 356 </a> 357 <a href="<?php echo esc_url( $later_url ); ?>"> 358 <?php esc_html_e( 'Remind me later', 'la-terreta-food-labels-for-woocommerce' ); ?> 359 </a> 360 </p> 361 </div> 362 <?php 363 } 364 add_action( 'admin_notices', 'ietiq_free_milestone_notice' ); 365 366 /** 367 * Gestionar las acciones del aviso de logro (descartar / posponer) 368 */ 369 function ietiq_free_handle_milestone_action() { 370 if ( ! isset( $_GET['ietiq_milestone_action'], $_GET['_ietiq_milestone_nonce'] ) ) return; 371 if ( ! wp_verify_nonce( sanitize_key( $_GET['_ietiq_milestone_nonce'] ), 'ietiq_milestone_action' ) ) return; 372 if ( ! is_user_logged_in() ) return; 373 374 $user_id = get_current_user_id(); 375 $action = sanitize_key( $_GET['ietiq_milestone_action'] ); 376 377 if ( 'dismiss' === $action ) { 378 $value = isset( $_GET['ietiq_milestone_value'] ) ? absint( $_GET['ietiq_milestone_value'] ) : 0; 379 if ( $value ) { 380 update_user_meta( $user_id, 'ietiq_milestone_seen', $value ); 381 } 382 } elseif ( 'later' === $action ) { 383 update_user_meta( $user_id, 'ietiq_milestone_snooze_until', time() + 3 * DAY_IN_SECONDS ); 384 } 385 386 wp_safe_redirect( remove_query_arg( [ 'ietiq_milestone_action', 'ietiq_milestone_value', '_ietiq_milestone_nonce' ] ) ); 387 exit; 388 } 389 add_action( 'admin_init', 'ietiq_free_handle_milestone_action' ); 390 391 /** 280 392 * Ocultar la pestaña "Información adicional" de WooCommerce 281 393 */ … … 320 432 $nonce = wp_create_nonce( 'ietiq_welcome_action' ); 321 433 $dismiss_url = add_query_arg( [ 'ietiq_welcome_action' => 'dismiss', '_ietiq_welcome_nonce' => $nonce ] ); 434 $optin_url = add_query_arg( [ 'ietiq_welcome_action' => 'optin', '_ietiq_welcome_nonce' => $nonce ] ); 435 $already_optin = get_user_meta( $user_id, 'ietiq_marketing_optin', true ); 322 436 ?> 323 437 <div class="notice notice-success" style="border-left: 4px solid #00a32a; padding: 16px 20px;"> … … 344 458 </li> 345 459 </ol> 346 <p style="margin: 0 ;">460 <p style="margin: 0 0 10px 0;"> 347 461 <a href="<?php echo esc_url( $settings_url ); ?>" class="button button-primary" style="margin-right: 10px;"> 348 462 <?php esc_html_e( 'Go to Settings →', 'la-terreta-food-labels-for-woocommerce' ); ?> … … 352 466 </a> 353 467 </p> 468 <?php if ( ! $already_optin ) : ?> 469 <p style="margin: 0; padding-top: 10px; border-top: 1px solid #e2e2e2; color: #666; font-size: 13px;"> 470 📩 <?php esc_html_e( 'Want occasional tips on food label compliance (CE 1169/2011)? No spam, unsubscribe anytime.', 'la-terreta-food-labels-for-woocommerce' ); ?> 471 <a href="<?php echo esc_url( $optin_url ); ?>" style="font-weight: bold;"> 472 <?php esc_html_e( 'Yes, send me tips →', 'la-terreta-food-labels-for-woocommerce' ); ?> 473 </a> 474 </p> 475 <?php endif; ?> 354 476 </div> 355 477 <?php … … 365 487 if ( ! is_user_logged_in() ) return; 366 488 367 if ( 'dismiss' === sanitize_key( $_GET['ietiq_welcome_action'] ) ) { 489 $action = sanitize_key( $_GET['ietiq_welcome_action'] ); 490 491 if ( 'dismiss' === $action ) { 492 update_user_meta( get_current_user_id(), 'ietiq_welcome_dismissed', 1 ); 493 } elseif ( 'optin' === $action && current_user_can( 'manage_options' ) ) { 494 ietiq_free_record_marketing_optin( get_current_user_id() ); 368 495 update_user_meta( get_current_user_id(), 'ietiq_welcome_dismissed', 1 ); 369 496 } … … 372 499 exit; 373 500 } 501 502 /** 503 * Registra el opt-in de marketing usando el email de la cuenta de admin 504 * actual. Se guarda ÚNICAMENTE en la base de datos local de WordPress 505 * (wp_options), sin ninguna llamada a servicios externos — coherente con 506 * la política de privacidad del readme ("no collect or store any personal 507 * data outside your own WordPress database"). Conectarlo a una 508 * herramienta de email marketing real (Mailchimp, ConvertKit...) requiere 509 * un paso aparte y, si se añade, declarar el servicio externo en el 510 * readme.txt (regla de WP.org). 511 */ 512 function ietiq_free_record_marketing_optin( $user_id ) { 513 update_user_meta( $user_id, 'ietiq_marketing_optin', time() ); 514 515 $user = get_userdata( $user_id ); 516 if ( ! $user || empty( $user->user_email ) ) { 517 return; 518 } 519 520 $optins = get_option( 'ietiq_marketing_optins', array() ); 521 if ( ! is_array( $optins ) ) { 522 $optins = array(); 523 } 524 525 foreach ( $optins as $entry ) { 526 if ( isset( $entry['email'] ) && $entry['email'] === $user->user_email ) { 527 return; // ya registrado 528 } 529 } 530 531 $optins[] = array( 532 'email' => $user->user_email, 533 'date' => current_time( 'mysql' ), 534 'site' => home_url(), 535 ); 536 537 update_option( 'ietiq_marketing_optins', $optins, false ); 538 } 539 540 /** 541 * Exportar los opt-ins de marketing a CSV (uso manual del administrador, 542 * ninguna llamada automática a servicios externos) 543 */ 544 function ietiq_free_export_marketing_optins() { 545 if ( ! current_user_can( 'manage_options' ) ) { 546 wp_die( esc_html__( 'Insufficient permissions.', 'la-terreta-food-labels-for-woocommerce' ) ); 547 } 548 check_admin_referer( 'ietiq_export_optins' ); 549 550 $optins = get_option( 'ietiq_marketing_optins', array() ); 551 if ( ! is_array( $optins ) ) { 552 $optins = array(); 553 } 554 555 nocache_headers(); 556 header( 'Content-Type: text/csv; charset=utf-8' ); 557 header( 'Content-Disposition: attachment; filename=ietiq-marketing-optins.csv' ); 558 559 $out = fopen( 'php://output', 'w' ); 560 fputcsv( $out, array( 'email', 'date', 'site' ) ); 561 foreach ( $optins as $entry ) { 562 fputcsv( $out, array( 563 isset( $entry['email'] ) ? $entry['email'] : '', 564 isset( $entry['date'] ) ? $entry['date'] : '', 565 isset( $entry['site'] ) ? $entry['site'] : '', 566 ) ); 567 } 568 fclose( $out ); 569 exit; 570 } 571 add_action( 'admin_post_ietiq_export_marketing_optins', 'ietiq_free_export_marketing_optins' ); 572 573 /** 574 * Mostrar el contador de opt-ins y el enlace de descarga CSV al final de 575 * la página de ajustes 576 */ 577 function ietiq_free_render_marketing_optins_box() { 578 if ( ! current_user_can( 'manage_options' ) ) return; 579 580 $optins = get_option( 'ietiq_marketing_optins', array() ); 581 if ( ! is_array( $optins ) || empty( $optins ) ) return; 582 583 $export_url = wp_nonce_url( admin_url( 'admin-post.php?action=ietiq_export_marketing_optins' ), 'ietiq_export_optins' ); 584 ?> 585 <hr style="margin: 30px 0 20px;" /> 586 <h2><?php esc_html_e( 'Email tips subscribers', 'la-terreta-food-labels-for-woocommerce' ); ?></h2> 587 <p> 588 <?php 589 printf( 590 /* translators: %d: number of subscribers */ 591 esc_html( _n( '%d admin opted in to receive occasional compliance tips.', '%d admins opted in to receive occasional compliance tips.', count( $optins ), 'la-terreta-food-labels-for-woocommerce' ) ), 592 count( $optins ) 593 ); 594 ?> 595 <a href="<?php echo esc_url( $export_url ); ?>" class="button"><?php esc_html_e( 'Download CSV', 'la-terreta-food-labels-for-woocommerce' ); ?></a> 596 </p> 597 <p class="description"><?php esc_html_e( 'Stored locally in your WordPress database only — nothing is sent anywhere automatically.', 'la-terreta-food-labels-for-woocommerce' ); ?></p> 598 <?php 599 } 600 add_action( 'ietiq_after_settings_page', 'ietiq_free_render_marketing_optins_box' ); 374 601 add_action( 'admin_init', 'ietiq_free_handle_welcome_action' ); 602 603 /** 604 * Encuesta de desactivación: antes de desactivar preguntamos el motivo 605 * (opcional, se puede saltar sin rellenar nada) y, si el motivo es que 606 * falta una función, mostramos un aviso de que está en Premium. El motivo 607 * se guarda solo localmente (wp_options), nunca se envía a ningún sitio. 608 */ 609 function ietiq_free_deactivation_survey_assets( $hook ) { 610 if ( 'plugins.php' !== $hook ) { 611 return; 612 } 613 614 $reasons = array( 615 'missing_feature' => __( 'Missing a feature I need (QR codes, shipping labels, unlimited products...)', 'la-terreta-food-labels-for-woocommerce' ), 616 'too_complex' => __( 'Too complex or hard to set up', 'la-terreta-food-labels-for-woocommerce' ), 617 'found_bug' => __( 'Found a bug', 'la-terreta-food-labels-for-woocommerce' ), 618 'switched' => __( 'Switched to another plugin', 'la-terreta-food-labels-for-woocommerce' ), 619 'temporary' => __( 'Temporary deactivation, I will reactivate', 'la-terreta-food-labels-for-woocommerce' ), 620 'other' => __( 'Other', 'la-terreta-food-labels-for-woocommerce' ), 621 ); 622 623 ?> 624 <div id="ietiq-deactivate-modal" style="display:none;position:fixed;inset:0;z-index:100000;background:rgba(0,0,0,0.5);"> 625 <div style="background:#fff;max-width:480px;margin:10vh auto;padding:24px;border-radius:4px;box-shadow:0 4px 20px rgba(0,0,0,0.2);"> 626 <h2 style="margin-top:0;"><?php esc_html_e( 'Quick question before you go', 'la-terreta-food-labels-for-woocommerce' ); ?></h2> 627 <p><?php esc_html_e( 'What made you deactivate Print Product Labels? (optional, helps us improve)', 'la-terreta-food-labels-for-woocommerce' ); ?></p> 628 <p> 629 <?php foreach ( $reasons as $key => $label ) : ?> 630 <label style="display:block;margin-bottom:6px;"> 631 <input type="radio" name="ietiq_deactivate_reason" value="<?php echo esc_attr( $key ); ?>" /> 632 <?php echo esc_html( $label ); ?> 633 </label> 634 <?php endforeach; ?> 635 </p> 636 <p id="ietiq-deactivate-premium-note" style="display:none;background:#fff8e5;border-left:4px solid #f39c12;padding:10px 12px;margin:10px 0;"> 637 <?php esc_html_e( 'Good news: that\'s exactly what Premium adds.', 'la-terreta-food-labels-for-woocommerce' ); ?> 638 <a href="https://www.laterretagames.com/imprimir-etiquetas-productos-premium-plugin-woocommerce/" target="_blank" style="font-weight:bold;"> 639 <?php esc_html_e( 'See Premium →', 'la-terreta-food-labels-for-woocommerce' ); ?> 640 </a> 641 </p> 642 <textarea id="ietiq-deactivate-note" placeholder="<?php esc_attr_e( 'Anything else? (optional)', 'la-terreta-food-labels-for-woocommerce' ); ?>" style="width:100%;height:60px;margin-bottom:14px;"></textarea> 643 <p style="text-align:right;margin-bottom:0;"> 644 <button type="button" class="button" id="ietiq-deactivate-skip"><?php esc_html_e( 'Skip & Deactivate', 'la-terreta-food-labels-for-woocommerce' ); ?></button> 645 <button type="button" class="button button-primary" id="ietiq-deactivate-submit"><?php esc_html_e( 'Submit & Deactivate', 'la-terreta-food-labels-for-woocommerce' ); ?></button> 646 </p> 647 </div> 648 </div> 649 <?php 650 $ajax_url = admin_url( 'admin-ajax.php' ); 651 $nonce = wp_create_nonce( 'ietiq_deactivation_feedback' ); 652 $basename = esc_js( IETIQ_FREE_PLUGIN_BASENAME ); 653 ?> 654 <script> 655 jQuery(function ($) { 656 var row = $('tr[data-plugin="<?php echo $basename; ?>"]'); 657 var deactivateLink = row.find('.deactivate a'); 658 if (!deactivateLink.length) { return; } 659 660 var targetUrl = deactivateLink.attr('href'); 661 var modal = $('#ietiq-deactivate-modal'); 662 var premiumNote = $('#ietiq-deactivate-premium-note'); 663 664 deactivateLink.on('click', function (e) { 665 e.preventDefault(); 666 modal.show(); 667 }); 668 669 $('input[name="ietiq_deactivate_reason"]').on('change', function () { 670 premiumNote.toggle($(this).val() === 'missing_feature'); 671 }); 672 673 modal.on('click', function (e) { 674 if (e.target === this) { modal.hide(); } 675 }); 676 677 $('#ietiq-deactivate-skip').on('click', function () { 678 window.location.href = targetUrl; 679 }); 680 681 $('#ietiq-deactivate-submit').on('click', function () { 682 var reason = $('input[name="ietiq_deactivate_reason"]:checked').val() || ''; 683 var note = $('#ietiq-deactivate-note').val() || ''; 684 var btn = $(this); 685 btn.prop('disabled', true); 686 687 $.post('<?php echo esc_url_raw( $ajax_url ); ?>', { 688 action: 'ietiq_free_deactivation_feedback', 689 nonce: '<?php echo esc_js( $nonce ); ?>', 690 reason: reason, 691 note: note 692 }).always(function () { 693 window.location.href = targetUrl; 694 }); 695 }); 696 }); 697 </script> 698 <?php 699 } 700 add_action( 'admin_footer', 'ietiq_free_deactivation_survey_assets' ); 701 702 /** 703 * Guarda el motivo de desactivación — solo localmente (wp_options), sin 704 * ninguna llamada a servicios externos. 705 */ 706 function ietiq_free_handle_deactivation_feedback() { 707 check_ajax_referer( 'ietiq_deactivation_feedback', 'nonce' ); 708 709 if ( ! current_user_can( 'activate_plugins' ) ) { 710 wp_send_json_error(); 711 } 712 713 $allowed_reasons = array( 'missing_feature', 'too_complex', 'found_bug', 'switched', 'temporary', 'other' ); 714 $reason = isset( $_POST['reason'] ) ? sanitize_key( wp_unslash( $_POST['reason'] ) ) : ''; 715 if ( ! in_array( $reason, $allowed_reasons, true ) ) { 716 $reason = ''; 717 } 718 $note = isset( $_POST['note'] ) ? sanitize_textarea_field( wp_unslash( $_POST['note'] ) ) : ''; 719 720 if ( $reason || $note ) { 721 $feedback = get_option( 'ietiq_deactivation_feedback', array() ); 722 if ( ! is_array( $feedback ) ) { 723 $feedback = array(); 724 } 725 $feedback[] = array( 726 'reason' => $reason, 727 'note' => $note, 728 'date' => current_time( 'mysql' ), 729 ); 730 update_option( 'ietiq_deactivation_feedback', $feedback, false ); 731 } 732 733 wp_send_json_success(); 734 } 735 add_action( 'wp_ajax_ietiq_free_deactivation_feedback', 'ietiq_free_handle_deactivation_feedback' ); 375 736 376 737 add_action('before_woocommerce_init', function() { -
la-terreta-food-labels-for-woocommerce/trunk/lib/design.php
r3545025 r3675014 550 550 </ul> 551 551 </p> 552 <p class="form-field" style="color:#666;font-size:12px;"> 553 🚀 <?php 554 printf( 555 /* translators: %s: link to the Premium page */ 556 esc_html__( 'Premium adds per-variation net weight, conservation/consumption method and QR code. %s', 'la-terreta-food-labels-for-woocommerce' ), 557 '<a href="https://www.laterretagames.com/imprimir-etiquetas-productos-premium-plugin-woocommerce/" target="_blank" style="font-weight:bold;">' . esc_html__( 'See Premium →', 'la-terreta-food-labels-for-woocommerce' ) . '</a>' 558 ); 559 ?> 560 </p> 552 561 </div> 553 562 <?php -
la-terreta-food-labels-for-woocommerce/trunk/lib/functions.php
r3595095 r3675014 249 249 $etiquetasPagina = 5; 250 250 251 // Cargar logo una sola vez antes del bucle252 $logo_id = (int) get_option('ietiq_company_logo_id', 0);253 $logo_path = '';254 if ($logo_id) {255 $logo_file = get_attached_file($logo_id);256 if ($logo_file && file_exists($logo_file)) {257 $logo_path = $logo_file;258 }259 }260 261 251 $items = $order->get_items(); 262 252 … … 400 390 $pdf->Rect($marginLeft, $Y, $pdf->getPageWidth() - 40, 45, 'D', array('all' => $style)); 401 391 402 // Logo de empresa — esquina superior derecha de la etiqueta403 if ($logo_path) {404 $logo_x = $marginLeft + ($pdf->getPageWidth() - 40) - 38;405 try {406 $pdf->Image($logo_path, $logo_x, $Y + 2, 35, 14, '', '', '', true, 150, '', false, false, 0, 'C');407 } catch (Exception $e) {408 // No se puede renderizar el logo, continuar sin él409 }410 }411 412 392 $pdf->Ln(10); 413 393 $item_counter++; -
la-terreta-food-labels-for-woocommerce/trunk/lib/menu.php
r3595095 r3675014 57 57 register_setting('ietiq_datos_grupo', 'ietiq_provincia', array('sanitize_callback' => 'sanitize_text_field')); 58 58 register_setting('ietiq_datos_grupo', 'ietiq_pais', array('sanitize_callback' => 'sanitize_text_field')); 59 register_setting('ietiq_datos_grupo', 'ietiq_company_logo_id', array('sanitize_callback' => 'absint'));60 59 61 60 // Añadir sección … … 84 83 add_settings_field('ietiq_pais', __('Country', 'la-terreta-food-labels-for-woocommerce'), 85 84 'ietiq_campo_pais', 'ietiq_datos', 'ietiq_datos_seccion'); 86 87 add_settings_field('ietiq_company_logo_id', __('Company Logo', 'la-terreta-food-labels-for-woocommerce'),88 'ietiq_campo_company_logo', 'ietiq_datos', 'ietiq_datos_seccion');89 85 } 90 86 … … 262 258 echo '<input type="checkbox" name="ietiq_mostrarMeta" value="1" ' . checked(1, $mostrarMeta, false) . ' />'; 263 259 } 264 265 function ietiq_campo_company_logo() {266 $logo_id = (int) get_option('ietiq_company_logo_id', 0);267 $logo_url = $logo_id ? wp_get_attachment_image_url($logo_id, array(300, 100)) : '';268 $has_logo = ! empty($logo_url);269 ?>270 <div id="ietiq-logo-container">271 <img272 id="ietiq-logo-preview"273 src="<?php echo $has_logo ? esc_url($logo_url) : ''; ?>"274 alt=""275 style="max-width:220px;max-height:80px;display:<?php echo $has_logo ? 'block' : 'none'; ?>;margin-bottom:8px;border:1px solid #ddd;padding:6px;background:#fff;"276 />277 <input type="hidden" id="ietiq_company_logo_id" name="ietiq_company_logo_id" value="<?php echo esc_attr($logo_id ?: ''); ?>" />278 <button type="button" id="ietiq-upload-logo" class="button">279 <?php esc_html_e('Select Logo', 'la-terreta-food-labels-for-woocommerce'); ?>280 </button>281 <button type="button" id="ietiq-remove-logo" class="button" style="margin-left:8px;<?php echo $has_logo ? '' : 'display:none;'; ?>">282 <?php esc_html_e('Remove', 'la-terreta-food-labels-for-woocommerce'); ?>283 </button>284 <p class="description" style="margin-top:8px;">285 <?php esc_html_e('Logo appears in the top-right corner of each product label. PNG with transparent background recommended (min. 300 px wide).', 'la-terreta-food-labels-for-woocommerce'); ?>286 </p>287 </div>288 <?php289 }290 291 /**292 * Encolar media library en la página Company Information293 */294 function ietiq_free_enqueue_logo_scripts($hook) {295 if ('ietiq_ajustes_page_ietiq_datos' !== $hook) {296 return;297 }298 wp_enqueue_media();299 $title = esc_js(__('Select Company Logo', 'la-terreta-food-labels-for-woocommerce'));300 $use = esc_js(__('Use this image', 'la-terreta-food-labels-for-woocommerce'));301 $js = "302 jQuery(function(jq) {303 var mediaFrame;304 jq('#ietiq-upload-logo').on('click', function(e) {305 e.preventDefault();306 if (mediaFrame) { mediaFrame.open(); return; }307 mediaFrame = wp.media({308 title: '{$title}',309 button: { text: '{$use}' },310 multiple: false,311 library: { type: 'image' }312 });313 mediaFrame.on('select', function() {314 var att = mediaFrame.state().get('selection').first().toJSON();315 jq('#ietiq_company_logo_id').val(att.id);316 jq('#ietiq-logo-preview').attr('src', att.url).show();317 jq('#ietiq-remove-logo').show();318 });319 mediaFrame.open();320 });321 jq('#ietiq-remove-logo').on('click', function(e) {322 e.preventDefault();323 jq('#ietiq_company_logo_id').val('');324 jq('#ietiq-logo-preview').attr('src', '').hide();325 jq(this).hide();326 });327 });328 ";329 wp_add_inline_script('jquery', $js);330 }331 add_action('admin_enqueue_scripts', 'ietiq_free_enqueue_logo_scripts');332 260 333 261 /****************** PÁGINAS DE AJUSTES **********************/ … … 347 275 ?> 348 276 </form> 277 278 <?php do_action('ietiq_after_settings_page'); ?> 349 279 </div> 350 280 <?php … … 365 295 ?> 366 296 </form> 297 <p class="description"> 298 🚀 <?php 299 printf( 300 /* translators: %s: link to the Premium page */ 301 esc_html__( 'Want your logo printed on every label? That\'s a %s feature.', 'la-terreta-food-labels-for-woocommerce' ), 302 '<a href="https://www.laterretagames.com/imprimir-etiquetas-productos-premium-plugin-woocommerce/" target="_blank" style="font-weight:bold;">' . esc_html__( 'Premium', 'la-terreta-food-labels-for-woocommerce' ) . '</a>' 303 ); 304 ?> 305 </p> 367 306 </div> 368 307 <?php -
la-terreta-food-labels-for-woocommerce/trunk/readme.txt
r3595095 r3675014 5 5 Requires at least: 5.8 6 6 Tested up to: 6.9 7 Stable tag: 3.1. 77 Stable tag: 3.1.8 8 8 Requires PHP: 7.4 9 9 License: GPLv2 or later … … 43 43 * ✅ Company data on every label 44 44 * ✅ Available in 4 languages: English, Spanish, French, German 45 * ✅ Company logo on every label (upload in Company Information settings)46 45 * ✅ Works with WooCommerce HPOS (High-Performance Order Storage) 47 46 … … 50 49 Upgrade to **Premium** to cover the full EU Regulation 1169/2011 and save time with professional tools: 51 50 51 * ✨ **Company logo** printed on every label 52 52 * ✨ **Net weight** on the label (required for pre-packaged foods) 53 53 * ✨ **Conservation & consumption instructions** … … 147 147 == Changelog == 148 148 149 = 3.1.8 = 150 * Added Documentation/Support/Rate/Premium links under the plugin name on the Plugins screen 151 * Added optional "send me tips" opt-in in the welcome notice (stored locally only, never sent anywhere automatically) 152 * Added a usage-milestone notice (25/100/250/500/1000 labels printed) pointing to Premium 153 * Added a contextual Premium note on the "Ingredients" tab of product variations 154 * Added a deactivation feedback survey with an optional link to Premium 155 149 156 = 3.1.7 = 150 * Added company logo on product labels (upload PNG/JPG in Company Information settings, appears top-right of each label)157 * Minor fixes 151 158 152 159 = 3.1.6 = -
la-terreta-food-labels-for-woocommerce/trunk/vendor/composer/installed.php
r3545025 r3675014 4 4 'pretty_version' => 'dev-main', 5 5 'version' => 'dev-main', 6 'reference' => ' c98f78e21b3590ada393add8ba390939d20656de',6 'reference' => '3ea9113eb151d022085cd81c44060fbf742be4fe', 7 7 'type' => 'wordpress-plugin', 8 8 'install_path' => __DIR__ . '/../../', … … 14 14 'pretty_version' => 'dev-main', 15 15 'version' => 'dev-main', 16 'reference' => ' c98f78e21b3590ada393add8ba390939d20656de',16 'reference' => '3ea9113eb151d022085cd81c44060fbf742be4fe', 17 17 'type' => 'wordpress-plugin', 18 18 'install_path' => __DIR__ . '/../../',
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)