Skip to content

Commit 3a41849

Browse files
committed
v0.7.5
1 parent 072d044 commit 3a41849

6 files changed

Lines changed: 184 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ All notable changes to `woo-order-images` will be documented in this file.
44

55
This project follows a pragmatic release history rather than a strict changelog format for older versions. Recent releases are documented in more detail.
66

7+
## [0.7.5] - 2026-04-15
8+
9+
### Added
10+
- PDF Invoices & Packing Slips for WooCommerce integration: WOI customer-uploaded images now appear as inline thumbnails on invoices and packing slips. Thumbnails are embedded as base64 JPEG data URIs so the PDF renderer never makes an HTTP request, making it compatible with both admin-triggered PDFs and automated order-status emails.
11+
- Added a `Plugin URI` header for Woo Order Images, pointing to the GitHub project page so admin plugin lists (including WooCommerce status reports) can show a direct project link.
12+
713
## [0.7.4] - 2026-03-29
814

915
### Fixed

includes/class-woi-admin-order-images.php

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1752,4 +1752,99 @@ private function extend_tile_edges( $tile_img, $copy_x, $copy_y, $copy_w, $copy_
17521752
imagecopyresampled( $tile_img, $tile_img, $copy_right, 0, $copy_right - 1, 0, $full_w - $copy_right, $full_h, 1, $full_h );
17531753
}
17541754
}
1755+
1756+
/**
1757+
* Generate a base64-encoded JPEG data URI of the cropped WOI image for embedding in PDF documents.
1758+
*
1759+
* Uses the item's stored spec (visible dimensions, puzzle config) and image entry (URL, crop, rotation)
1760+
* to produce a small thumbnail suitable for mPDF/Dompdf without any HTTP requests.
1761+
*
1762+
* @param WC_Order_Item_Product $wc_item The order line-item.
1763+
* @param array $image_entry Single entry from the _woi_images meta array.
1764+
* @param int $thumb_px Maximum dimension (px) of the output thumbnail.
1765+
* @return string Data URI string, or empty string on failure.
1766+
*/
1767+
public static function generate_pdf_thumbnail_data_uri( $wc_item, $image_entry, $thumb_px = 120 ) {
1768+
$instance = new self();
1769+
1770+
$url = isset( $image_entry['url'] ) ? (string) $image_entry['url'] : '';
1771+
$crop = isset( $image_entry['crop'] ) && is_array( $image_entry['crop'] ) ? $image_entry['crop'] : array();
1772+
$rotation = isset( $image_entry['rotation'] ) ? WOI_Order_Images::normalize_rotation_value( $image_entry['rotation'] ) : 0;
1773+
1774+
if ( '' === $url ) {
1775+
return '';
1776+
}
1777+
1778+
$base_spec = $instance->get_item_spec( $wc_item );
1779+
1780+
// Build a no-bleed spec for thumbnail rendering so the output contains only the
1781+
// visible area without wrap-margin strips, which look odd at small sizes.
1782+
$thumb_spec = $base_spec;
1783+
$thumb_spec['wrap_margin'] = 0.0;
1784+
$thumb_spec['full_width'] = $base_spec['visible_width'];
1785+
$thumb_spec['full_height'] = $base_spec['visible_height'];
1786+
$thumb_spec['visible_width_percent'] = 100.0;
1787+
$thumb_spec['visible_height_percent'] = 100.0;
1788+
1789+
if ( ! empty( $base_spec['is_puzzle'] ) ) {
1790+
// For puzzle items, show the full assembled image rather than individual tiles.
1791+
$cols = max( 1, (int) $base_spec['puzzle_cols'] );
1792+
$rows = max( 1, (int) $base_spec['puzzle_rows'] );
1793+
$entry_cols = isset( $image_entry['puzzle_cols'] ) ? max( 0, (int) $image_entry['puzzle_cols'] ) : 0;
1794+
$entry_rows = isset( $image_entry['puzzle_rows'] ) ? max( 0, (int) $image_entry['puzzle_rows'] ) : 0;
1795+
if ( $entry_cols > 0 && $entry_rows > 0 ) {
1796+
$cols = $entry_cols;
1797+
$rows = $entry_rows;
1798+
}
1799+
$thumb_spec['visible_width'] = $base_spec['visible_width'] * $cols;
1800+
$thumb_spec['visible_height'] = $base_spec['visible_height'] * $rows;
1801+
$thumb_spec['full_width'] = $thumb_spec['visible_width'];
1802+
$thumb_spec['full_height'] = $thumb_spec['visible_height'];
1803+
$thumb_spec['visible_aspect_ratio'] = $thumb_spec['visible_height'] > 0
1804+
? $thumb_spec['visible_width'] / $thumb_spec['visible_height']
1805+
: 1.0;
1806+
} else {
1807+
$thumb_spec = $instance->get_oriented_spec_for_crop( $thumb_spec, $url, $crop, $rotation );
1808+
}
1809+
1810+
$jpeg = $instance->build_single_tile_jpeg( $url, $crop, $thumb_spec, $rotation );
1811+
if ( empty( $jpeg ) ) {
1812+
return '';
1813+
}
1814+
1815+
// Downsample to thumbnail dimensions so the PDF stays compact.
1816+
$src = @imagecreatefromstring( $jpeg );
1817+
if ( ! $src ) {
1818+
return '';
1819+
}
1820+
1821+
$sw = imagesx( $src );
1822+
$sh = imagesy( $src );
1823+
$scale = min( 1.0, (float) $thumb_px / max( 1, max( $sw, $sh ) ) );
1824+
$tw = max( 1, (int) round( $sw * $scale ) );
1825+
$th = max( 1, (int) round( $sh * $scale ) );
1826+
1827+
$thumb = imagecreatetruecolor( $tw, $th );
1828+
if ( ! $thumb ) {
1829+
imagedestroy( $src );
1830+
return '';
1831+
}
1832+
1833+
$white = imagecolorallocate( $thumb, 255, 255, 255 );
1834+
imagefill( $thumb, 0, 0, $white );
1835+
imagecopyresampled( $thumb, $src, 0, 0, 0, 0, $tw, $th, $sw, $sh );
1836+
imagedestroy( $src );
1837+
1838+
ob_start();
1839+
imagejpeg( $thumb, null, 85 );
1840+
$thumb_jpeg = ob_get_clean();
1841+
imagedestroy( $thumb );
1842+
1843+
if ( empty( $thumb_jpeg ) ) {
1844+
return '';
1845+
}
1846+
1847+
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
1848+
return 'data:image/jpeg;base64,' . base64_encode( $thumb_jpeg );
1849+
}
17551850
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
if ( ! defined( 'ABSPATH' ) ) {
4+
exit;
5+
}
6+
7+
/**
8+
* Integrates Woo Order Images thumbnails into PDF Invoices & Packing Slips for WooCommerce
9+
* (plugin slug: woocommerce-pdf-invoices-packing-slips, class: WPO_WCPDF).
10+
*
11+
* Hooks into wpo_wcpdf_after_item_meta to inject a small cropped JPEG thumbnail,
12+
* encoded as a data URI, directly into the PDF HTML before the renderer sees it.
13+
* This avoids any HTTP requests from the PDF engine (mPDF/Dompdf), so it works
14+
* regardless of authentication context (admin-triggered or automated email).
15+
*/
16+
class WOI_PDF_Invoices {
17+
18+
public function init() {
19+
// Register the hook unconditionally — it will never fire if WPO WCPDF is absent.
20+
add_action( 'wpo_wcpdf_after_item_meta', array( $this, 'inject_thumbnails' ), 10, 3 );
21+
}
22+
23+
/**
24+
* Output thumbnail(s) for a line item's WOI images into the PDF document.
25+
*
26+
* @param string $document_type WPO document type slug ('invoice', 'packing-slip', etc.).
27+
* @param array $item WPO-processed item data array. Key 'item' holds the
28+
* underlying WC_Order_Item_Product object.
29+
* @param WC_Order $order The WooCommerce order.
30+
*/
31+
public function inject_thumbnails( $document_type, $item, $order ) {
32+
if ( ! is_array( $item ) || ! isset( $item['item'] ) ) {
33+
return;
34+
}
35+
36+
$wc_item = $item['item'];
37+
if ( ! $wc_item instanceof WC_Order_Item_Product ) {
38+
return;
39+
}
40+
41+
$images = $wc_item->get_meta( WOI_Order_Images::ORDER_META_IMAGES, true );
42+
if ( empty( $images ) || ! is_array( $images ) ) {
43+
return;
44+
}
45+
46+
$thumb_html = '';
47+
foreach ( $images as $image_entry ) {
48+
if ( empty( $image_entry['url'] ) ) {
49+
continue;
50+
}
51+
52+
$data_uri = WOI_Admin_Order_Images::generate_pdf_thumbnail_data_uri( $wc_item, $image_entry );
53+
if ( '' === $data_uri ) {
54+
continue;
55+
}
56+
57+
// Inline style only — mPDF/Dompdf have limited CSS support.
58+
// max-height drives the row height; width:auto preserves aspect ratio.
59+
$thumb_html .= '<img src="' . esc_attr( $data_uri ) . '" '
60+
. 'style="max-height:60px;max-width:60px;width:auto;height:auto;'
61+
. 'display:inline-block;vertical-align:middle;margin:2px;" alt="">';
62+
}
63+
64+
if ( '' === $thumb_html ) {
65+
return;
66+
}
67+
68+
echo '<div style="margin-top:4px;line-height:0;">' . $thumb_html . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
69+
}
70+
}

includes/class-woi-plugin.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
require_once WOI_PLUGIN_DIR . 'includes/class-woi-frontend.php';
1010
require_once WOI_PLUGIN_DIR . 'includes/class-woi-order-images.php';
1111
require_once WOI_PLUGIN_DIR . 'includes/class-woi-settings.php';
12+
require_once WOI_PLUGIN_DIR . 'includes/class-woi-pdf-invoices.php';
1213

1314
class WOI_Plugin {
1415
private static $instance = null;
@@ -36,5 +37,8 @@ public function init() {
3637

3738
$admin_order_images = new WOI_Admin_Order_Images();
3839
$admin_order_images->init();
40+
41+
$pdf_invoices = new WOI_PDF_Invoices();
42+
$pdf_invoices->init();
3943
}
4044
}

readme.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Tags: woocommerce, product images, image upload, printing, puzzle
44
Requires at least: 6.8
55
Tested up to: 6.9.4
66
Requires PHP: 7.4
7-
Stable tag: 0.7.4
7+
Stable tag: 0.7.5
88
License: GPLv2 or later
99
License URI: https://www.gnu.org/licenses/gpl-2.0.html
1010

@@ -23,6 +23,7 @@ Key capabilities include:
2323
* Order-level print-sheet generation
2424
* Puzzle layouts with portrait and landscape grid support
2525
* Global print bleed, margins, watermark text, and page size settings
26+
* Optional integration with PDF Invoices & Packing Slips for WooCommerce (by WP Overnight) — customer-uploaded images appear as inline thumbnails on invoices and packing slips
2627

2728
== Installation ==
2829

@@ -70,6 +71,10 @@ This plugin bundles the following third-party library:
7071

7172
== Changelog ==
7273

74+
= 0.7.5 =
75+
* Added integration with PDF Invoices & Packing Slips for WooCommerce (by WP Overnight): customer-uploaded images now appear as inline thumbnails on invoices and packing slips. Thumbnails are embedded as JPEG data URIs so the PDF renderer makes no HTTP requests, making it compatible with both admin-triggered and automated email PDFs.
76+
* Added a `Plugin URI` header pointing to the GitHub project so admin plugin lists (including WooCommerce status reports) can link WOI to its project page.
77+
7378
= 0.7.4 =
7479
* Fixed the GitHub release workflow to build from the exact pushed ref and to fail if a pushed tag version does not match the plugin version in the checked-out files.
7580
* Released the shared thumbnail-resolution and customer DPI warning improvements in a correctly versioned package.

woo-order-images.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
<?php
22
/**
33
* Plugin Name: Woo Order Images
4+
* Plugin URI: https://github.com/timriker/woo-order-images
45
* Description: Collects customer image uploads for WooCommerce products and generates order print sheets, including puzzle layouts.
5-
* Version: 0.7.4
6+
* Version: 0.7.5
67
* Requires at least: 6.8
78
* Requires PHP: 7.4
89
* Requires Plugins: woocommerce
@@ -20,7 +21,7 @@
2021
}
2122

2223
if ( ! defined( 'WOI_VERSION' ) ) {
23-
define( 'WOI_VERSION', '0.7.4' );
24+
define( 'WOI_VERSION', '0.7.5' );
2425
}
2526

2627
if ( ! defined( 'WOI_PLUGIN_FILE' ) ) {

0 commit comments

Comments
 (0)