Plugin Directory

Changeset 3675014


Ignore:
Timestamp:
08/31/2026 10:38:29 PM (7 weeks ago)
Author:
laterretagames
Message:

Version 3.1.8

Location:
la-terreta-food-labels-for-woocommerce
Files:
54 deleted
12 edited
1 copied

Legend:

Unmodified
Added
Removed
  • la-terreta-food-labels-for-woocommerce/tags/3.1.8/la-terreta-food-labels-for-woocommerce.php

    r3595095 r3675014  
    44 * Plugin URI: https://www.laterretagames.com/imprimir-etiquetas-productos-premium-plugin-woocommerce/
    55 * 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.7
     6 * Version: 3.1.8
    77 * Author: La Terreta Games
    88 * Author URI: https://laterretagames.com
    … …  
    2323}
    2424
    25 define('IETIQ_FREE_VERSION', '3.1.7');
     25define('IETIQ_FREE_VERSION', '3.1.8');
    2626define('IETIQ_FREE_PLUGIN_DIR', plugin_dir_path(__FILE__));
    2727define('IETIQ_FREE_PLUGIN_URL', plugin_dir_url(__FILE__));
    … …  
    124124}
    125125add_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 */
     131function 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}
     145add_filter( 'plugin_row_meta', 'ietiq_free_plugin_row_meta', 10, 2 );
    126146
    127147/**
    … …  
    278298
    279299/**
     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 */
     304function 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}
     364add_action( 'admin_notices', 'ietiq_free_milestone_notice' );
     365
     366/**
     367 * Gestionar las acciones del aviso de logro (descartar / posponer)
     368 */
     369function 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}
     389add_action( 'admin_init', 'ietiq_free_handle_milestone_action' );
     390
     391/**
    280392 * Ocultar la pestaña "Información adicional" de WooCommerce
    281393 */
    … …  
    320432    $nonce        = wp_create_nonce( 'ietiq_welcome_action' );
    321433    $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 );
    322436    ?>
    323437    <div class="notice notice-success" style="border-left: 4px solid #00a32a; padding: 16px 20px;">
    … …  
    344458            </li>
    345459        </ol>
    346         <p style="margin: 0;">
     460        <p style="margin: 0 0 10px 0;">
    347461            <a href="<?php echo esc_url( $settings_url ); ?>" class="button button-primary" style="margin-right: 10px;">
    348462                <?php esc_html_e( 'Go to Settings →', 'la-terreta-food-labels-for-woocommerce' ); ?>
    … …  
    352466            </a>
    353467        </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; ?>
    354476    </div>
    355477    <?php
    … …  
    365487    if ( ! is_user_logged_in() ) return;
    366488
    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() );
    368495        update_user_meta( get_current_user_id(), 'ietiq_welcome_dismissed', 1 );
    369496    }
    … …  
    372499    exit;
    373500}
     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 */
     512function 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 */
     544function 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}
     571add_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 */
     577function 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}
     600add_action( 'ietiq_after_settings_page', 'ietiq_free_render_marketing_optins_box' );
    374601add_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 */
     609function 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}
     700add_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 */
     706function 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}
     735add_action( 'wp_ajax_ietiq_free_deactivation_feedback', 'ietiq_free_handle_deactivation_feedback' );
    375736
    376737add_action('before_woocommerce_init', function() {
  • la-terreta-food-labels-for-woocommerce/tags/3.1.8/lib/design.php

    r3545025 r3675014  
    550550            </ul>
    551551        </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>
    552561    </div>
    553562    <?php
  • la-terreta-food-labels-for-woocommerce/tags/3.1.8/lib/functions.php

    r3595095 r3675014  
    249249        $etiquetasPagina = 5;
    250250
    251         // Cargar logo una sola vez antes del bucle
    252         $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 
    261251        $items = $order->get_items();
    262252
    … …  
    400390            $pdf->Rect($marginLeft, $Y, $pdf->getPageWidth() - 40, 45, 'D', array('all' => $style));
    401391
    402             // Logo de empresa — esquina superior derecha de la etiqueta
    403             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 él
    409                 }
    410             }
    411 
    412392            $pdf->Ln(10);
    413393            $item_counter++;
  • la-terreta-food-labels-for-woocommerce/tags/3.1.8/lib/menu.php

    r3595095 r3675014  
    5757    register_setting('ietiq_datos_grupo', 'ietiq_provincia', array('sanitize_callback' => 'sanitize_text_field'));
    5858    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'));
    6059
    6160    // Añadir sección
    … …  
    8483    add_settings_field('ietiq_pais', __('Country', 'la-terreta-food-labels-for-woocommerce'),
    8584        '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');
    8985}
    9086
    … …  
    262258    echo '<input type="checkbox" name="ietiq_mostrarMeta" value="1" ' . checked(1, $mostrarMeta, false) . ' />';
    263259}
    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         <img
    272             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     <?php
    289 }
    290 
    291 /**
    292  * Encolar media library en la página Company Information
    293  */
    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');
    332260
    333261/******************  PÁGINAS DE AJUSTES  **********************/
    … …  
    347275            ?>
    348276        </form>
     277
     278        <?php do_action('ietiq_after_settings_page'); ?>
    349279    </div>
    350280    <?php
    … …  
    365295            ?>
    366296        </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>
    367306    </div>
    368307    <?php
  • la-terreta-food-labels-for-woocommerce/tags/3.1.8/readme.txt

    r3595095 r3675014  
    55Requires at least: 5.8
    66Tested up to: 6.9
    7 Stable tag: 3.1.7
     7Stable tag: 3.1.8
    88Requires PHP: 7.4
    99License: GPLv2 or later
    … …  
    4343* ✅ Company data on every label
    4444* ✅ Available in 4 languages: English, Spanish, French, German
    45 * ✅ Company logo on every label (upload in Company Information settings)
    4645* ✅ Works with WooCommerce HPOS (High-Performance Order Storage)
    4746
    … …  
    5049Upgrade to **Premium** to cover the full EU Regulation 1169/2011 and save time with professional tools:
    5150
     51* ✨ **Company logo** printed on every label
    5252* ✨ **Net weight** on the label (required for pre-packaged foods)
    5353* ✨ **Conservation & consumption instructions**
    … …  
    147147== Changelog ==
    148148
     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
    149156= 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
    151158
    152159= 3.1.6 =
  • la-terreta-food-labels-for-woocommerce/tags/3.1.8/vendor/composer/installed.php

    r3545025 r3675014  
    44        'pretty_version' => 'dev-main',
    55        'version' => 'dev-main',
    6         'reference' => 'c98f78e21b3590ada393add8ba390939d20656de',
     6        'reference' => '3ea9113eb151d022085cd81c44060fbf742be4fe',
    77        'type' => 'wordpress-plugin',
    88        'install_path' => __DIR__ . '/../../',
    … …  
    1414            'pretty_version' => 'dev-main',
    1515            'version' => 'dev-main',
    16             'reference' => 'c98f78e21b3590ada393add8ba390939d20656de',
     16            'reference' => '3ea9113eb151d022085cd81c44060fbf742be4fe',
    1717            'type' => 'wordpress-plugin',
    1818            'install_path' => __DIR__ . '/../../',
  • la-terreta-food-labels-for-woocommerce/trunk/la-terreta-food-labels-for-woocommerce.php

    r3595095 r3675014  
    44 * Plugin URI: https://www.laterretagames.com/imprimir-etiquetas-productos-premium-plugin-woocommerce/
    55 * 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.7
     6 * Version: 3.1.8
    77 * Author: La Terreta Games
    88 * Author URI: https://laterretagames.com
    … …  
    2323}
    2424
    25 define('IETIQ_FREE_VERSION', '3.1.7');
     25define('IETIQ_FREE_VERSION', '3.1.8');
    2626define('IETIQ_FREE_PLUGIN_DIR', plugin_dir_path(__FILE__));
    2727define('IETIQ_FREE_PLUGIN_URL', plugin_dir_url(__FILE__));
    … …  
    124124}
    125125add_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 */
     131function 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}
     145add_filter( 'plugin_row_meta', 'ietiq_free_plugin_row_meta', 10, 2 );
    126146
    127147/**
    … …  
    278298
    279299/**
     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 */
     304function 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}
     364add_action( 'admin_notices', 'ietiq_free_milestone_notice' );
     365
     366/**
     367 * Gestionar las acciones del aviso de logro (descartar / posponer)
     368 */
     369function 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}
     389add_action( 'admin_init', 'ietiq_free_handle_milestone_action' );
     390
     391/**
    280392 * Ocultar la pestaña "Información adicional" de WooCommerce
    281393 */
    … …  
    320432    $nonce        = wp_create_nonce( 'ietiq_welcome_action' );
    321433    $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 );
    322436    ?>
    323437    <div class="notice notice-success" style="border-left: 4px solid #00a32a; padding: 16px 20px;">
    … …  
    344458            </li>
    345459        </ol>
    346         <p style="margin: 0;">
     460        <p style="margin: 0 0 10px 0;">
    347461            <a href="<?php echo esc_url( $settings_url ); ?>" class="button button-primary" style="margin-right: 10px;">
    348462                <?php esc_html_e( 'Go to Settings →', 'la-terreta-food-labels-for-woocommerce' ); ?>
    … …  
    352466            </a>
    353467        </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; ?>
    354476    </div>
    355477    <?php
    … …  
    365487    if ( ! is_user_logged_in() ) return;
    366488
    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() );
    368495        update_user_meta( get_current_user_id(), 'ietiq_welcome_dismissed', 1 );
    369496    }
    … …  
    372499    exit;
    373500}
     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 */
     512function 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 */
     544function 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}
     571add_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 */
     577function 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}
     600add_action( 'ietiq_after_settings_page', 'ietiq_free_render_marketing_optins_box' );
    374601add_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 */
     609function 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}
     700add_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 */
     706function 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}
     735add_action( 'wp_ajax_ietiq_free_deactivation_feedback', 'ietiq_free_handle_deactivation_feedback' );
    375736
    376737add_action('before_woocommerce_init', function() {
  • la-terreta-food-labels-for-woocommerce/trunk/lib/design.php

    r3545025 r3675014  
    550550            </ul>
    551551        </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>
    552561    </div>
    553562    <?php
  • la-terreta-food-labels-for-woocommerce/trunk/lib/functions.php

    r3595095 r3675014  
    249249        $etiquetasPagina = 5;
    250250
    251         // Cargar logo una sola vez antes del bucle
    252         $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 
    261251        $items = $order->get_items();
    262252
    … …  
    400390            $pdf->Rect($marginLeft, $Y, $pdf->getPageWidth() - 40, 45, 'D', array('all' => $style));
    401391
    402             // Logo de empresa — esquina superior derecha de la etiqueta
    403             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 él
    409                 }
    410             }
    411 
    412392            $pdf->Ln(10);
    413393            $item_counter++;
  • la-terreta-food-labels-for-woocommerce/trunk/lib/menu.php

    r3595095 r3675014  
    5757    register_setting('ietiq_datos_grupo', 'ietiq_provincia', array('sanitize_callback' => 'sanitize_text_field'));
    5858    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'));
    6059
    6160    // Añadir sección
    … …  
    8483    add_settings_field('ietiq_pais', __('Country', 'la-terreta-food-labels-for-woocommerce'),
    8584        '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');
    8985}
    9086
    … …  
    262258    echo '<input type="checkbox" name="ietiq_mostrarMeta" value="1" ' . checked(1, $mostrarMeta, false) . ' />';
    263259}
    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         <img
    272             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     <?php
    289 }
    290 
    291 /**
    292  * Encolar media library en la página Company Information
    293  */
    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');
    332260
    333261/******************  PÁGINAS DE AJUSTES  **********************/
    … …  
    347275            ?>
    348276        </form>
     277
     278        <?php do_action('ietiq_after_settings_page'); ?>
    349279    </div>
    350280    <?php
    … …  
    365295            ?>
    366296        </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>
    367306    </div>
    368307    <?php
  • la-terreta-food-labels-for-woocommerce/trunk/readme.txt

    r3595095 r3675014  
    55Requires at least: 5.8
    66Tested up to: 6.9
    7 Stable tag: 3.1.7
     7Stable tag: 3.1.8
    88Requires PHP: 7.4
    99License: GPLv2 or later
    … …  
    4343* ✅ Company data on every label
    4444* ✅ Available in 4 languages: English, Spanish, French, German
    45 * ✅ Company logo on every label (upload in Company Information settings)
    4645* ✅ Works with WooCommerce HPOS (High-Performance Order Storage)
    4746
    … …  
    5049Upgrade to **Premium** to cover the full EU Regulation 1169/2011 and save time with professional tools:
    5150
     51* ✨ **Company logo** printed on every label
    5252* ✨ **Net weight** on the label (required for pre-packaged foods)
    5353* ✨ **Conservation & consumption instructions**
    … …  
    147147== Changelog ==
    148148
     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
    149156= 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
    151158
    152159= 3.1.6 =
  • la-terreta-food-labels-for-woocommerce/trunk/vendor/composer/installed.php

    r3545025 r3675014  
    44        'pretty_version' => 'dev-main',
    55        'version' => 'dev-main',
    6         'reference' => 'c98f78e21b3590ada393add8ba390939d20656de',
     6        'reference' => '3ea9113eb151d022085cd81c44060fbf742be4fe',
    77        'type' => 'wordpress-plugin',
    88        'install_path' => __DIR__ . '/../../',
    … …  
    1414            'pretty_version' => 'dev-main',
    1515            'version' => 'dev-main',
    16             'reference' => 'c98f78e21b3590ada393add8ba390939d20656de',
     16            'reference' => '3ea9113eb151d022085cd81c44060fbf742be4fe',
    1717            'type' => 'wordpress-plugin',
    1818            'install_path' => __DIR__ . '/../../',
Note: See TracChangeset for help on using the changeset viewer.