Plugin Directory

Changeset 3467629


Ignore:
Timestamp:
02/23/2026 11:33:01 AM (7 days ago)
Author:
webtoffee
Message:

4.9.2 2026-02-23

  • [Fix] - Fixed TypeError in shipping label print button on order list page.
  • [Fix] - Prevent footer overlap in DOMPDF by disabling “stick to bottom” when footer exceeds 40 words.
  • [Tweak] - Optimize PDF generation by embedding images as base64 to avoid remote fetch delays.
  • [Compatibility] - WooCommerce 10.5.2
Location:
print-invoices-packing-slip-labels-for-woocommerce/trunk
Files:
1 added
4 deleted
10 edited

Legend:

Unmodified
Added
Removed
  • print-invoices-packing-slip-labels-for-woocommerce/trunk/admin/modules/banner/assets/css/wt-gdpr-promotion-banner-cta.css

    r3382552 r3467629  
    1717    line-height: 34px;
    1818    letter-spacing: 0%;
    19     color: #0066FE;
     19    color: #212121;
    2020}
    2121
     
    3333
    3434.wt-banner-clarity-inactive .wt-body-section .wt-body-content {
    35     max-width: 670px;
     35    max-width: 950px;
    3636}
    3737
     
    4040    justify-content: space-between;
    4141    align-items: center;
    42     margin-top: 15px;
    4342}
    4443
     
    6564
    6665.wt-gdpr-promotion-banner-cta .wt-body-section .wt-button-wrap .certificate-section-wrap .certificate-image img {
    67     max-width: 100%;
    68     max-height: 40px;
     66    max-width: none;
    6967    width: auto;
    70     height: auto;
     68    height: 50px;
    7169    object-fit: contain;
    7270}
     
    124122   
    125123    .wt-gdpr-promotion-banner-cta .wt-body-section .wt-button-wrap .certificate-section-wrap .certificate-image img {
    126         max-width: 50px;
    127         max-height: 35px;
     124        max-width: 80px;
     125        max-height: 48px;
    128126    }
    129127}
  • print-invoices-packing-slip-labels-for-woocommerce/trunk/admin/modules/banner/class-wt-gdpr-cta-banner.php

    r3382552 r3467629  
    5959
    6060        /**
     61         * Google Site Kit plugin slug
     62         *
     63         * @var string
     64         */
     65        protected $sitekit_plugin = 'google-site-kit/google-site-kit.php';
     66
     67        /**
    6168         * Promotion link for when Clarity is active
    6269         *
     
    7380
    7481        /**
     82         * Promotion link for when Google Site Kit is active
     83         *
     84         * @var string
     85         */
     86        private static $sitekit_promotion_link = "https://www.webtoffee.com/product/gdpr-cookie-consent/?utm_source=free_plugin_pdf_invoice&utm_medium=pdf_invoice_premium&utm_campaign=GDPR_SiteKit";
     87
     88        /**
    7589         * Current promotion link (set after conditions are checked)
    7690         *
     
    8094
    8195        /**
    82          * Banner text (set based on Clarity status)
    83          * 
     96         * Banner text (set based on Clarity/Site Kit status)
     97         *
    8498         * @var string
    8599         */
     
    88102        /**
    89103         * Is Clarity active flag
    90          * 
     104         *
    91105         * @var bool|null
    92106         */
     
    94108
    95109        /**
     110         * Is Google Site Kit active flag
     111         *
     112         * @var bool|null
     113         */
     114        protected $is_sitekit_active = null;
     115
     116        /**
    96117         * Check if Microsoft Clarity plugin is active
    97          * 
     118         *
    98119         * @return bool
    99120         */
    100121        protected function is_clarity_active() {
    101             if ($this->is_clarity_active === null) {
    102                 $this->is_clarity_active = $this->is_plugin_active_anywhere($this->clarity_plugin);
     122            if ( $this->is_clarity_active === null ) {
     123                $this->is_clarity_active = $this->is_plugin_active_anywhere( $this->clarity_plugin );
    103124            }
    104125            return $this->is_clarity_active;
     
    106127
    107128        /**
    108          * Set the appropriate promotion link and banner text based on Clarity status
    109          * Called after all banner conditions are met
    110          *
     129         * Check if Google Site Kit plugin is active
     130         *
     131         * @return bool
     132         */
     133        protected function is_sitekit_active() {
     134            if ( $this->is_sitekit_active === null ) {
     135                $this->is_sitekit_active = $this->is_plugin_active_anywhere( $this->sitekit_plugin );
     136            }
     137            return $this->is_sitekit_active;
     138        }
     139
     140        /**
     141         * Set the appropriate promotion link and banner text based on Clarity/Site Kit status.
     142         * Priority: Site Kit (IAB TCF) > Clarity > default.
     143         * Called after all banner conditions are met.
     144         *
    111145         * @return void
    112146         */
    113147        protected function set_banner_contents() {
    114             if ($this->is_clarity_active()) {
     148            if ( $this->is_sitekit_active() ) {
     149                $this->promotion_link = self::$sitekit_promotion_link;
     150                $this->banner_text = __( 'Under IAB Europe’s TCF policy, publishers participating in TCF must upgrade to TCF v2.3 by <b>28 February 2026</b> to remain compliant. <br>Ensure uninterrupted ad monetization with the <b>WebToffee GDPR Cookie Consent Plugin</b> – fully supporting <b>TCF v2.3</b>.', 'print-invoices-packing-slip-labels-for-woocommerce' );
     151            } elseif ( $this->is_clarity_active() ) {
    115152                $this->promotion_link = self::$clarity_promotion_link;
    116                 $this->banner_text = __('<b>Important Update:</b> Starting October 31, 2025, Microsoft requires websites to use Clarity Consent V2 to continue collecting analytical data. Ensure compliance by upgrading to the GDPR Cookie Consent Plugin, now fully compatible with <b>Clarity Consent V2</b> and <b>Google Consent Mode</b>.', 'print-invoices-packing-slip-labels-for-woocommerce');
     153                $this->banner_text = __( '<b>Important Update:</b> Starting October 31, 2025, Microsoft requires websites to use Clarity Consent V2 to continue collecting analytical data. <br>Ensure compliance by upgrading to the GDPR Cookie Consent Plugin, now fully compatible with <b>Clarity Consent V2</b> and <b>Google Consent Mode</b>.', 'print-invoices-packing-slip-labels-for-woocommerce' );
    117154            } else {
    118155                $this->promotion_link = self::$default_promotion_link;
    119                 $this->banner_text = __('Stay compliant with GDPR and US Privacy Laws using our Google-certified CMP plugin—now with <b>Microsoft Clarity Consent V2</b>, <b>UET Consent Mode</b> and <b>Google Consent Mode</b> support.', 'print-invoices-packing-slip-labels-for-woocommerce');
     156                $this->banner_text = __( 'Stay compliant with GDPR and US Privacy Laws using our Google-certified CMP plugin—now with <b>Microsoft Clarity Consent V2</b>, <br><b>UET Consent Mode</b> and <b>Google Consent Mode</b> support.', 'print-invoices-packing-slip-labels-for-woocommerce' );
    120157            }
    121158        }
     
    257294                    <div class="wt-gdpr-promotion-banner-content-wrap">
    258295                        <div class="wt-header-section">
    259                             <p class="wt-header-title"><?php esc_html_e('Ensure Cookie Compliance for Your WordPress Website', 'print-invoices-packing-slip-labels-for-woocommerce'); ?></p>
     296                            <p class="wt-header-title"><?php echo esc_html( $this->is_sitekit_active() ? __( 'Are you running third-party ads?', 'print-invoices-packing-slip-labels-for-woocommerce' ) : __( 'Ensure Cookie Compliance for Your WordPress Website', 'print-invoices-packing-slip-labels-for-woocommerce' ) ); ?></p>
    260297                        </div>
    261298                        <div class="wt-body-section">
     
    273310                                <div class="certificate-section-wrap">
    274311                                    <div class="certificate-image">
    275                                         <img src="<?php echo esc_url(plugin_dir_url( __FILE__ ) . 'assets/images/gdpr.png'); ?>" alt="<?php echo esc_attr__('Certified Partner', 'print-invoices-packing-slip-labels-for-woocommerce'); ?>">
     312                                        <img src="<?php echo esc_url(plugin_dir_url( __FILE__ ) . 'assets/images/gdpr.svg'); ?>" alt="<?php echo esc_attr__('Certified Partner', 'print-invoices-packing-slip-labels-for-woocommerce'); ?>">
    276313                                    </div>
    277314                                </div>
  • print-invoices-packing-slip-labels-for-woocommerce/trunk/admin/modules/customizer/classes/class-customizer.php

    r3399740 r3467629  
    809809        }
    810810        $img_url = apply_filters( 'wt_pklist_alter_product_image_url', $img_url, $product_id, $variation_id, $parent_id );
    811         return '<img src="' . esc_attr( $img_url ) . '" style="border-radius:25%;' . $style . '" class="wfte_product_image_thumb"/>';
     811        $style   = apply_filters( 'wt_pklist_alter_product_image_style', $style, $product_id, $variation_id, $parent_id );
     812
     813        return '<img src="' . esc_attr( $img_url ) . '" style="border-radius:25%;' . esc_attr($style) . '" class="wfte_product_image_thumb"/>';
    812814    }
    813815
  • print-invoices-packing-slip-labels-for-woocommerce/trunk/admin/modules/customizer/customizer.php

    r3457991 r3467629  
    12041204        $html = $this->replace_placeholders($find_replace, $html, $template_type);
    12051205        $html = Wf_Woocommerce_Packing_List_Admin::qrcode_barcode_visibility($html, $template_type);
     1206       
     1207        // Convert images to base64 for PDF generation to prevent slow downloads
     1208        if ($this->template_for_pdf) {
     1209            $html = $this->convert_images_to_base64($html);
     1210        }
     1211       
    12061212        return apply_filters('wt_pklist_alter_final_order_template_html', $html, $template_type, $order, $box_packing, $order_package, $this->template_for_pdf);
    12071213    }
     
    13251331        $replace = array_values($find_replace);
    13261332        $html = str_replace($find, $replace, $html);
     1333        return $html;
     1334    }
     1335   
     1336    /**
     1337     * Get image mime type (based on woocommerce-pdf-invoices-packing-slips)
     1338     *
     1339     * @param string $src
     1340     * @param string|null $data Optional image data for remote files
     1341     * @return string
     1342     */
     1343    private function get_image_mime_type($src, $data = null)
     1344    {
     1345        $mime_type = '';
     1346
     1347        if (empty($src)) {
     1348            return $mime_type;
     1349        }
     1350
     1351        $is_remote = filter_var($src, FILTER_VALIDATE_URL);
     1352
     1353        // Check if 'getimagesize' function exists and try to get mime type for local files
     1354        if (function_exists('getimagesize') && !$is_remote) {
     1355            $image_info = @getimagesize($src);
     1356
     1357            if ($image_info && isset($image_info['mime'])) {
     1358                $mime_type = $image_info['mime'];
     1359            }
     1360        }
     1361
     1362        // Fallback to 'finfo_file' if mime type is empty for local files only
     1363        if (empty($mime_type) && function_exists('finfo_open') && !$is_remote) {
     1364            $finfo = finfo_open(FILEINFO_MIME_TYPE);
     1365
     1366            if ($finfo) {
     1367                $mime_type = finfo_file($finfo, $src);
     1368               
     1369                if (PHP_VERSION_ID < 80100) {
     1370                    finfo_close($finfo);
     1371                }
     1372            }
     1373        }
     1374
     1375        // Handle remote files - try getimagesizefromstring if we have data
     1376        if (empty($mime_type) && $data !== null && function_exists('getimagesizefromstring')) {
     1377            $image_info = @getimagesizefromstring($data);
     1378
     1379            if ($image_info && isset($image_info['mime'])) {
     1380                $mime_type = $image_info['mime'];
     1381            }
     1382        }
     1383
     1384        // Handle remote files - try finfo_buffer if we have data
     1385        if (empty($mime_type) && $data !== null && function_exists('finfo_open')) {
     1386            $finfo = finfo_open(FILEINFO_MIME_TYPE);
     1387
     1388            if ($finfo) {
     1389                $mime_type = finfo_buffer($finfo, $data);
     1390               
     1391                if (PHP_VERSION_ID < 80100) {
     1392                    finfo_close($finfo);
     1393                }
     1394            }
     1395        }
     1396
     1397        // Determine using WP functions
     1398        if (empty($mime_type)) {
     1399            $path = wp_parse_url($src, PHP_URL_PATH);
     1400            $file_info = wp_check_filetype($path);
     1401            $mime_type = isset($file_info['type']) ? $file_info['type'] : '';
     1402        }
     1403
     1404        // Last chance, determine from file extension
     1405        if (empty($mime_type)) {
     1406            $path = parse_url($src, PHP_URL_PATH);
     1407            $extension = strtolower(pathinfo($path, PATHINFO_EXTENSION));
     1408
     1409            switch ($extension) {
     1410                case 'jpg':
     1411                case 'jpeg':
     1412                    $mime_type = 'image/jpeg';
     1413                    break;
     1414                case 'png':
     1415                    $mime_type = 'image/png';
     1416                    break;
     1417                case 'gif':
     1418                    $mime_type = 'image/gif';
     1419                    break;
     1420                case 'bmp':
     1421                    $mime_type = 'image/bmp';
     1422                    break;
     1423                case 'webp':
     1424                    $mime_type = 'image/webp';
     1425                    break;
     1426                case 'svg':
     1427                    $mime_type = 'image/svg+xml';
     1428                    break;
     1429            }
     1430        }
     1431
     1432        return $mime_type;
     1433    }
     1434
     1435    /**
     1436     * Base64 encode file from local path (based on woocommerce-pdf-invoices-packing-slips)
     1437     *
     1438     * @param string $local_path
     1439     * @return string|bool
     1440     */
     1441    private function base64_encode_file($local_path)
     1442    {
     1443        if (empty($local_path)) {
     1444            return false;
     1445        }
     1446
     1447        $file_data = @file_get_contents($local_path);
     1448
     1449        return $file_data ? base64_encode($file_data) : false;
     1450    }
     1451
     1452    /**
     1453     * Get image source in base64 format (based on woocommerce-pdf-invoices-packing-slips)
     1454     *
     1455     * @param string $src
     1456     * @return string|array Returns array with 'mime' and 'data' keys, or false on failure
     1457     */
     1458    private function get_image_src_in_base64($src)
     1459    {
     1460        if (empty($src)) {
     1461            return false;
     1462        }
     1463
     1464        // Skip if already base64 encoded
     1465        if (strpos($src, 'data:image') === 0 || strpos($src, 'base64') !== false || strpos($src, 'broken_image') !== false) {
     1466            return false;
     1467        }
     1468
     1469        $upload = wp_upload_dir();
     1470        $path = null;
     1471
     1472        // Try to convert URL to local path
     1473        if (strpos($src, $upload['baseurl']) !== false) {
     1474            $path = str_replace($upload['baseurl'], $upload['basedir'], $src);
     1475        } elseif (strpos($src, home_url()) !== false || strpos($src, '/') === 0) {
     1476            $parsed = parse_url($src);
     1477            $path = ABSPATH . ltrim(isset($parsed['path']) ? $parsed['path'] : $src, '/');
     1478        }
     1479
     1480        // Normalize path
     1481        if ($path) {
     1482            $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
     1483        }
     1484
     1485        $image_data = null;
     1486        $local_src = $src;
     1487
     1488        // Try local file first (fastest)
     1489        if ($path && is_readable($path)) {
     1490            $image_data = @file_get_contents($path);
     1491            if ($image_data !== false) {
     1492                $local_src = $path;
     1493            }
     1494        }
     1495
     1496        // Fallback to remote URL if local file not found
     1497        if ($image_data === null && filter_var($src, FILTER_VALIDATE_URL)) {
     1498            $image_data = @file_get_contents($src);
     1499        }
     1500
     1501        if ($image_data === false || $image_data === null) {
     1502            return false;
     1503        }
     1504
     1505        $mime_type = $this->get_image_mime_type($local_src, $image_data);
     1506
     1507        if (empty($mime_type)) {
     1508            return false;
     1509        }
     1510
     1511        $image_base64 = base64_encode($image_data);
     1512
     1513        if (!$image_base64) {
     1514            return false;
     1515        }
     1516
     1517        return array('mime' => $mime_type, 'data' => $image_base64);
     1518    }
     1519
     1520    /**
     1521     * Convert image URLs to base64 data URIs for PDF generation
     1522     * Based on woocommerce-pdf-invoices-packing-slips approach
     1523     * @param string $html Template HTML
     1524     * @return string HTML with images converted to base64
     1525     */
     1526    private function convert_images_to_base64($html)
     1527    {
     1528        $get_base64 = array($this, 'get_image_src_in_base64');
     1529
     1530        $html = preg_replace_callback('/<img([^>]*?)\s+src\s*=\s*["\']([^"\']+)["\']([^>]*?)>/i',
     1531            function ($m) use ($get_base64) {
     1532                $img = call_user_func($get_base64, trim($m[2]));
     1533                return $img ? '<img' . $m[1] . ' src="data:' . $img['mime'] . ';base64,' . $img['data'] . '"' . $m[3] . '>' : $m[0];
     1534            }, $html);
     1535
     1536        $html = preg_replace_callback('/background-image:\s*url\(["\']?([^"\']+)["\']?\)/i',
     1537            function ($m) use ($get_base64) {
     1538                $img = call_user_func($get_base64, trim($m[1]));
     1539                return $img ? 'background-image: url(data:' . $img['mime'] . ';base64,' . $img['data'] . ')' : $m[0];
     1540            }, $html);
     1541
    13271542        return $html;
    13281543    }
  • print-invoices-packing-slip-labels-for-woocommerce/trunk/changelog.txt

    r3457991 r3467629  
    11== Changelog ==
     2
     3= 4.9.1 2026-02-10 =
     4* [Fix] - Prevent fatal error array before calling in_array() in packing slip.
     5* [Tweak] - Keep SKU enabled by default in invoice and packing slip documents.
     6* [Add] - Added live preview for packing slip, dispatch label, and delivery note documents.
     7* [Compatibility] - WooCommerce 10.5.0
     8* [Compatibility] - WordPress 6.9.1
    29
    310= 4.9.0 2025-12-17 =
  • print-invoices-packing-slip-labels-for-woocommerce/trunk/includes/class-wf-woocommerce-packing-list.php

    r3457991 r3467629  
    117117        }else
    118118        {
    119             $this->version = '4.9.1';
    120             self::$base_version = '4.9.1';
     119            $this->version = '4.9.2';
     120            self::$base_version = '4.9.2';
    121121        }
    122122        if(defined('WF_PKLIST_PLUGIN_NAME'))
     
    203203         */
    204204        require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/admin/class-wf-woocommerce-packing-list-admin_notices.php';
    205 
    206         /**
    207          * Includes the Black Friday and Cyber Monday CTA banners for 2024
    208          */
    209         require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/modules/banner/class-wt-bfcm-twenty-twenty-five.php';
    210205
    211206        /**
  • print-invoices-packing-slip-labels-for-woocommerce/trunk/print-invoices-packing-slip-labels-for-woocommerce.php

    r3457991 r3467629  
    1414 * Plugin URI:        https://www.webtoffee.com/product/woocommerce-pdf-invoices-packing-slips/
    1515 * Description:       Prints Packing List,Invoice,Delivery Note and Shipping Label.
    16  * Version:           4.9.1
     16 * Version:           4.9.2
    1717 * Author:            WebToffee
    1818 * Author URI:        https://www.webtoffee.com/
     
    2121 * Text Domain:       print-invoices-packing-slip-labels-for-woocommerce
    2222 * Domain Path:       /languages
    23  * WC tested up to:   10.5.0
     23 * WC tested up to:   10.5.2
    2424 */
    2525// If this file is called directly, abort.
     
    7272     * Currently plugin version.
    7373     */
    74     define('WF_PKLIST_VERSION', '4.9.1');
     74    define('WF_PKLIST_VERSION', '4.9.2');
    7575
    7676    if ( ! defined( 'WBTE_PKLIST_CROSS_PROMO_BANNER_VERSION' ) ) {
  • print-invoices-packing-slip-labels-for-woocommerce/trunk/public/modules/invoice/invoice.php

    r3421609 r3467629  
    19481948        $style_regex = '/<style id="template_font_style"[^>]*>[\s\S]*?<\/style>/';
    19491949        $updated_style = '<style id="template_font_style">*{font-family:"DeJaVu Sans", monospace;}.template_footer{/*position:absolute;bottom:0px;*/}</style>';
    1950 
    1951         $footer_to_the_bottom = apply_filters('wt_pklist_footer_to_the_bottom', true, $order, $template_type);
     1950       
     1951        $footer_to_bottom = true;
     1952        $footer_text = Wf_Woocommerce_Packing_List::get_option('woocommerce_wf_packinglist_footer');
     1953        $footer_text_word_count = str_word_count($footer_text);
     1954        if ($footer_text_word_count > 40) {
     1955            $footer_to_bottom = false;
     1956        }
     1957       
     1958        $footer_to_the_bottom = apply_filters('wt_pklist_footer_to_the_bottom', $footer_to_bottom, $order, $template_type);     
    19521959        if ($footer_to_the_bottom) {
    19531960            $updated_style = '<style id="template_font_style">*{font-family:"DeJaVu Sans", monospace;}.template_footer{position:absolute;bottom:0px;}</style>';
     
    20372044        $updated_style = '<style id="template_font_style">*{font-family:"DeJaVu Sans", monospace;}.template_footer{/*position:absolute;bottom:0px;*/}</style>';
    20382045
    2039         $footer_to_the_bottom = apply_filters('wt_pklist_footer_to_the_bottom', true, $order, $template_type);
    2040 
     2046        $footer_to_bottom = true;
     2047        $footer_text = Wf_Woocommerce_Packing_List::get_option('woocommerce_wf_packinglist_footer');
     2048        $footer_text_word_count = str_word_count($footer_text);
     2049        if ($footer_text_word_count > 40) {
     2050            $footer_to_bottom = false;
     2051        }
     2052
     2053        $footer_to_the_bottom = apply_filters('wt_pklist_footer_to_the_bottom', $footer_to_bottom, $order, $template_type);
    20412054        if ($footer_to_the_bottom) {
    20422055            $updated_style = '<style id="template_font_style">*{font-family:"DeJaVu Sans", monospace;}.template_footer{position:absolute;bottom:0px;}</style>';
  • print-invoices-packing-slip-labels-for-woocommerce/trunk/public/modules/shippinglabel/shippinglabel.php

    r3351991 r3467629  
    584584            $order_id   = version_compare( WC()->version, '2.7.0', '<' ) ? $order->id : $order->get_id();
    585585           
    586             if( in_array( $this->module_base, Wf_Woocommerce_Packing_List::get_option( 'wt_pklist_separate_print_button_enable' ) ) ) {
     586            $enabled_modules = Wf_Woocommerce_Packing_List::get_option('wt_pklist_separate_print_button_enable');
     587            $enabled_modules = is_array($enabled_modules) ? $enabled_modules : (array) $enabled_modules;
     588
     589            if ( in_array($this->module_base, $enabled_modules, true) ) {
     590                           
    587591                $btn_action_name    = 'wt_pklist_print_document_'.$this->module_base.'_not_yet';
    588592                $img_url            = WF_PKLIST_PLUGIN_URL . 'admin/images/'.$this->module_base.'.png';
  • print-invoices-packing-slip-labels-for-woocommerce/trunk/readme.txt

    r3457991 r3467629  
    1 === WebToffee WooCommerce PDF Invoices, Packing Slips, Delivery Notes and Shipping Labels ===
     1=== WebToffee WooCommerce PDF Invoices, Packing Slips, Delivery Notes & Shipping Labels ===
    22Contributors: WebToffee
    3 Version: 4.9.1
     3Version: 4.9.2
    44Donate link:https://www.webtoffee.com/product/woocommerce-pdf-invoices-packing-slips/
    55Tags: WooCommerce PDF invoices, WooCommerce invoice, packing slips, shipping label, woocommerce print invoice
    66Requires at least: 3.0.1
    77Tested up to: 6.9
    8 Stable tag: 4.9.1
     8Stable tag: 4.9.2
    99Requires PHP: 5.6
    1010License: GPLv2 or later
     
    1414
    1515== Description ==
    16 With the WebToffee WooCommerce PDF Invoices and Packing Slips plugin, your customers receive PDF invoices and packing slips automatically attached to their order confirmation emails. The plugin includes a customizable invoice template to get you started, and offers flexibility to edit or create your own WooCommerce invoice templates. You can easily download or print WooCommerce invoice PDFs, packing slips and shipping labels right from your WooCommerce order admin.
     16With the WebToffee WooCommerce PDF Invoices and Packing Slips plugin, your customers receive PDF invoices and packing slips automatically attached to their order confirmation emails. The plugin includes a customizable invoice template to get you started, and offers flexibility to edit or create your own WooCommerce custom invoice templates. You can easily download or print WooCommerce invoice PDFs, packing slips and shipping labels right from your WooCommerce order admin.
    1717
    1818Additionally, the WooCommerce invoice PDF and print packing slip plugin enables you to generate UBL and XML invoices, helping streamline your order fulfillment process.
    1919
    20 == Introduction ==
    21 
    22 WooCommerce Print PDF Invoices and Packing Slips Plugin for WooCommerce plugin helps you generate PDF invoices, packing lists / packing slips, delivery notes, dispatch labels and shipping labels from the WooCommerce orders page. WooCommerce, by default, doesn't allow you to print any of these documents from your orders page.
     20== PDF Invoices & Packing Slips for WooCommerce: An Overview ==
     21
     22WooCommerce Print PDF Invoices and Packing Slips Plugin helps generate PDF invoices, packing lists / packing slips, delivery notes, dispatch labels and shipping labels from the WooCommerce orders page. WooCommerce, by default, doesn't allow you to print any of these documents from your orders page.
    2323
    2424Beyond invoices and packing slips, the plugin makes it easy to create and print WooCommerce delivery notes that include essential details such as order items, customer information and shipping addresses. These documents help ensure accurate and smooth order handovers.
     
    3333
    3434
    35 == Features of WooCommerce PDF Invoices & Packing Slips for WooCommerce Plugin ==
     35== Features of WooCommerce PDF Invoices & Packing Slips Plugin ==
    3636
    3737* <strong>Supported documents</strong>: Creates and prints following PDF documents from WooCommerce order page.
     
    7474
    7575
    76 &#9989; Tested OK with WooCommerce 10.5.0
     76&#9989; Tested OK with WooCommerce 10.5.2
    7777&#9989; Tested OK up to PHP 8.2
    7878
     
    8282&#8226; [EU VAT Number - WooCommerce](https://woocommerce.com/products/eu-vat-number/)
    8383&#8226; [WooCommerce EU VAT Assistant. Aelia](https://aelia.co/shop/eu-vat-assistant-woocommerce/)
    84 &#8226; [WooCommerce Extra Product Potions by TM](https://plugintheme.net/shop/woocommerce-tm-extra-product-options/)
     84&#8226; [WooCommerce Extra Product Options by TM](https://plugintheme.net/shop/woocommerce-tm-extra-product-options/)
    8585&#8226; [Extra Product Options by Theme complete](https://codecanyon.net/item/woocommerce-extra-product-options/7908619)
    8686&#8226; [Multi-Currency for WooCommerce, by VillaTheme](https://villatheme.com/extensions/woo-multi-currency/)
     
    9292
    9393
    94 == Recommended Add-on plugins ==
     94== Recommended WooCommerce Invoices Add-ons ==
    9595For better Unicode and RTL language support for all the generated documents, we highly recommend using the below free add-on with our PDF Invoices, Packing slips, Delivery notes, and Shipping label plugin for WooCommerce.
    9696[mPDF add-on for PDF Invoices, Packing Slips, Delivery Notes and Shipping Labels by WebToffee](https://wordpress.org/plugins/mpdf-addon-for-pdf-invoices/ "RTL and Unicode language add-on for PDF invoice plugin by WebToffee").
     
    111111You only have to install the plugin that offers the documents that are required for you.
    112112
    113 == Key Features of WooCommerce Invoices Plugin & Add-ons ==
     113== Key Features of WooCommerce Invoices Plugin & Premium Add-ons ==
    114114<blockquote>
    115115
     
    149149For the complete list of features and details check out the [WooCommerce PDF Invoices, Packing Slips & Credit Notes plugin](https://www.webtoffee.com/product/woocommerce-pdf-invoices-packing-slips/?utm_source=free_plugin_readme&utm_medium=pdf_invoice&utm_campaign=PDF_invoice).
    150150
    151 == WooCommerce Print Shipping Labels, Dispatch Labels & Delivery Notes Plugin Premium Features ==
     151== WooCommerce Print Shipping Labels, Dispatch Labels & WooCommerce Delivery Notes Plugin Premium Features ==
    152152<blockquote>
    153153
     
    205205<li> Add additional details such as special notes, transport terms, and sales terms</li>
    206206<li> Enable code customizations for WooCommerce pro forma invoices</li>
     207<li> Add due date to proforma invoices</li>
    207208<li> Add custom footer to proforma invoices</li>
    208209</ul>
     
    234235* WordPress 3.0.1 or higher is recommended
    235236
    236 = Steps to install the plugin =
     237= Steps to install the WooCommerce PDF Invoice plugin =
    237238
    238239To install the plugin, follow the below steps:
     
    296297== Changelog ==
    297298
    298 = 4.9.1 2026-02-10 =
    299 * [Fix] - Prevent fatal error array before calling in_array() in packing slip.
    300 * [Tweak] - Keep SKU enabled by default in invoice and packing slip documents.
    301 * [Add] - Added live preview for packing slip, dispatch label, and delivery note documents.
    302 * [Compatibility] - WooCommerce 10.5.0
    303 * [Compatibility] - WordPress 6.9.1
     299= 4.9.2 2026-02-23 =
     300* [Fix] - Fixed TypeError in shipping label print button on order list page.
     301* [Fix] - Prevent footer overlap in DOMPDF by disabling “stick to bottom” when footer exceeds 40 words.
     302* [Tweak] - Optimize PDF generation by embedding images as base64 to avoid remote fetch delays.
     303* [Compatibility] - WooCommerce 10.5.2
    304304
    305305[See changelog for all versions](https://plugins.svn.wordpress.org/print-invoices-packing-slip-labels-for-woocommerce/trunk/changelog.txt)
     
    308308== Upgrade Notice ==
    309309
    310 = 4.9.1 =
    311 * [Fix] - Prevent fatal error array before calling in_array() in packing slip.
    312 * [Tweak] - Keep SKU enabled by default in invoice and packing slip documents.
    313 * [Add] - Added live preview for packing slip, dispatch label, and delivery note documents.
    314 * [Compatibility] - WooCommerce 10.5.0
    315 * [Compatibility] - WordPress 6.9.1
     310= 4.9.2 =
     311* [Fix] - Fixed TypeError in shipping label print button on order list page.
     312* [Fix] - Prevent footer overlap in DOMPDF by disabling “stick to bottom” when footer exceeds 40 words.
     313* [Tweak] - Optimize PDF generation by embedding images as base64 to avoid remote fetch delays.
     314* [Compatibility] - WooCommerce 10.5.2
Note: See TracChangeset for help on using the changeset viewer.