I know this has been a year, but I've managed to achieve this on 2.3.4. Hopefully this may help someone later down the line and saves them some time:
I'm not going to go through the technical parts of creating an extension. Assuming you know not to override the vendor folder, you'll know how to get the extension set up.
Anyway, here's my di.xml:
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Sales\Model\Order\Pdf\Shipment" type="Vendor\Module\Model\Order\Pdf\Shipment" />
</config>
To explain that, a lot of PDF modifications are done using the Order\Pdf\Invoice
model. That's for invoices (duh), what we need is Order\Pdf\Shipment
.
Next, we need to create our own model. Much like the invoice work you've probably seen, you need to extend the pdf class.
So in Vendor/Module/Model/Order/Pdf
I created Shipment.php
. This is the full code. I'll explain a couple bits afterwards:
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Vendor\Module\Model\Order\Pdf;
use Magento\Catalog\Model\ProductRepositoryFactory;
use Magento\Sales\Model\Order\Pdf\Invoice as InvoicePdf;
class Shipment extends \Magento\Sales\Model\Order\Pdf\Shipment
{
public function __construct(
\Magento\Payment\Helper\Data $paymentData,
\Magento\Framework\Stdlib\StringUtils $string,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Framework\Filesystem $filesystem,
\Magento\Sales\Model\Order\Pdf\Config $pdfConfig,
\Magento\Sales\Model\Order\Pdf\Total\Factory $pdfTotalFactory,
\Magento\Sales\Model\Order\Pdf\ItemsFactory $pdfItemsFactory,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
\Magento\Framework\Translate\Inline\StateInterface $inlineTranslation,
\Magento\Sales\Model\Order\Address\Renderer $addressRenderer,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\Locale\ResolverInterface $localeResolver,
\Magento\GiftMessage\Api\OrderRepositoryInterface $orderGiftRepo,
\Magento\Framework\ObjectManagerInterface $objectManager,
array $data = []
) {
parent::__construct(
$paymentData,
$string,
$scopeConfig,
$filesystem,
$pdfConfig,
$pdfTotalFactory,
$pdfItemsFactory,
$localeDate,
$inlineTranslation,
$addressRenderer,
$storeManager,
$localeResolver,
$data
);
$this->orderGiftRepo = $orderGiftRepo;
$this->_objectManager = $objectManager;
}
public function getPdf($shipments = [])
{
$this->_beforeGetPdf();
$this->_initRenderer('shipment');
$pdf = new \Zend_Pdf();
$this->_setPdf($pdf);
$style = new \Zend_Pdf_Style();
$this->_setFontBold($style, 10);
foreach ($shipments as $shipment) {
if ($shipment->getStoreId()) {
$this->_localeResolver->emulate($shipment->getStoreId());
$this->_storeManager->setCurrentStore($shipment->getStoreId());
}
$page = $this->newPage();
$order = $shipment->getOrder();
/* Add image */
$this->insertLogo($page, $shipment->getStore());
/* Add address */
$this->insertAddress($page, $shipment->getStore());
/* Add head */
$this->insertOrder(
$page,
$shipment,
$this->_scopeConfig->isSetFlag(
self::XML_PATH_SALES_PDF_SHIPMENT_PUT_ORDER_ID,
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
$order->getStoreId()
)
);
/* Add document text and number */
$this->insertDocumentNumber($page, __('Packing Slip # ') . $shipment->getIncrementId());
/* Add table */
$this->_drawHeader($page);
if($order->getId()) {
if ($order->getGiftMessageId() != 0) { //If there's no gift message, this will return 0. Need to catch it to prevent an exception.
if ($giftWrap = $this->getGiftMessages($order->getId())) {
//$logger->info("hello" . $order->getId());
$page->drawText(strip_tags(ltrim('### GIFT INFORMATION ###:')), 25, 815, 'UTF-8');
$page->drawText(strip_tags(ltrim('Sender: ' . $giftWrap["sender"])), 25, 800, 'UTF-8');
$page->drawText(strip_tags(ltrim('Recipient: ' . $giftWrap["recipient"])), 25, 785, 'UTF-8');
$page->drawText(strip_tags(ltrim('Message: ' . $giftWrap["message"])), 25, 770, 'UTF-8');
}
}
}
/* Add body */
foreach ($shipment->getAllItems() as $item) {
if ($item->getOrderItem()->getParentItem()) {
continue;
}
/* Draw item */
$this->_drawItem($item, $page, $order);
$page = end($pdf->pages);
}
if ($shipment->getStoreId()) {
$this->_localeResolver->revert();
}
}
$this->_afterGetPdf();
return $pdf;
}
public function getGiftMessages($order_id) {
$giftMessage = $this->orderGiftRepo->get($order_id);
return $giftMessage;
}
}
I needed to include the OrderRepositoryInterface
API (take a peek at vendor/magento/module-gift-message/api/
if you feel like it for reference).
I also needed to include all the parent references in the constructor class, otherwise you'll get an error.
I then included the getPdf
class from vendor/magento/module-sales/Model/Order/Pdf/Shipment.php
. I'm not really a back end specialist, so I don't know if it all needed to be included, but hey, it works.
The actual retrival of the message is straightforward:
public function getGiftMessages($order_id) {
$giftMessage = $this->orderGiftRepo->get($order_id);
return $giftMessage;
}
It needs the order ID. The ->get
method returns an array of recipient, sender
and message
.
Now for the most important section of code (which processes the gift data):
if($order->getId()) {
if ($order->getGiftMessageId() != 0) { //If there's no gift message, this will return 0. Need to catch it to prevent an exception.
if ($giftWrap = $this->getGiftMessages($order->getId())) {
//$logger->info("hello" . $order->getId());
$page->drawText(strip_tags(ltrim('### GIFT INFORMATION ###:')), 25, 815, 'UTF-8');
$page->drawText(strip_tags(ltrim('Sender: ' . $giftWrap["sender"])), 25, 800, 'UTF-8');
$page->drawText(strip_tags(ltrim('Recipient: ' . $giftWrap["recipient"])), 25, 785, 'UTF-8');
$page->drawText(strip_tags(ltrim('Message: ' . $giftWrap["message"])), 25, 770, 'UTF-8');
}
}
}
If you attempt to grab a gift message from an order when there's no gift message, Magento will error (I think it's a no such entity exception). I'm not exactly sure why this isn't more forgiving, but still.
Anyway, we need to firstly ensure the Order has a gift message. That's why I need $order->getGiftMessageId() != 0
. You see, any orders with a gift message ID of '0' don't have a gift message.
Now we're on the home straight!
if ($giftWrap = $this->getGiftMessages($order->getId())) {
//$logger->info("hello" . $order->getId());
$page->drawText(strip_tags(ltrim('### GIFT INFORMATION ###:')), 25, 815, 'UTF-8');
$page->drawText(strip_tags(ltrim('Sender: ' . $giftWrap["sender"])), 25, 800, 'UTF-8');
$page->drawText(strip_tags(ltrim('Recipient: ' . $giftWrap["recipient"])), 25, 785, 'UTF-8');
$page->drawText(strip_tags(ltrim('Message: ' . $giftWrap["message"])), 25, 770, 'UTF-8');
}
Now we're able to pull through the gift message details, we can then draw them in the correct place. I've chosen the top left hand corner of the page.
Test that, and it should work!