1

I have created Preference for Magento\Sales\Model\Order\Pdf\Invoice file, inside preference Invoice class I overwrite getPdf function but it is showing below error:

Exception #0 (Exception): Notice: Undefined property: Webkeon\Custompdf\Model\Order\Pdf\Invoice::$appEmulation

My code is below

/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Webkeon\Custompdf\Model\Order\Pdf;


/**
 * Sales Order Invoice PDF model
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class Invoice extends \Magento\Sales\Model\Order\Pdf\Invoice 
{
    
    /**
     * Draw header for item table
     *
     * @param \Zend_Pdf_Page $page
     * @return void
     */
    protected function _drawHeader(\Zend_Pdf_Page $page)
    {
        /* Add table head */
        $this->_setFontRegular($page, 10);
        $page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
        $page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.5));
        $page->setLineWidth(0.5);
        $page->drawRectangle(25, $this->y, 570, $this->y - 15);
        $this->y -= 10;
        $page->setFillColor(new \Zend_Pdf_Color_Rgb(0, 0, 0));

        //columns headers
        $lines[0][] = ['text' => __('Products'), 'feed' => 35];

        //$lines[0][] = ['text' => __('SKU'), 'feed' => 290, 'align' => 'right'];

        $lines[0][] = ['text' => __('Qty'), 'feed' => 435, 'align' => 'right'];

        $lines[0][] = ['text' => __('Price'), 'feed' => 360, 'align' => 'right'];

        $lines[0][] = ['text' => __('Tax'), 'feed' => 495, 'align' => 'right'];

        $lines[0][] = ['text' => __('Subtotal'), 'feed' => 565, 'align' => 'right'];

        $lineBlock = ['lines' => $lines, 'height' => 5];

        $this->drawLineBlocks($page, [$lineBlock], ['table_header' => true]);
        $page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
        $this->y -= 20;
    }

    /**
     * Return PDF document
     *
     * @param array|Collection $invoices
     * @return \Zend_Pdf
     */
    public function getPdf($invoices = [])
    {
        $this->_beforeGetPdf();
        $this->_initRenderer('invoice');

        $pdf = new \Zend_Pdf();
        $this->_setPdf($pdf);
        $style = new \Zend_Pdf_Style();
        $this->_setFontBold($style, 10);

        foreach ($invoices as $invoice) {
            if ($invoice->getStoreId()) {
                $this->appEmulation->startEnvironmentEmulation(
                    $invoice->getStoreId(),
                    \Magento\Framework\App\Area::AREA_FRONTEND,
                    true
                );
                $this->_storeManager->setCurrentStore($invoice->getStoreId());
            }
            $page = $this->newPage();
            $order = $invoice->getOrder();
            $this->y = 730;
            /* Add image */
            //$this->insertLogo($page, $invoice->getStore());
            /* Add address */
           // $this->insertAddress($page, $invoice->getStore());
            /* Add head */
            $this->insertOrder(
                $page,
                $invoice,
                $order,
                $this->_scopeConfig->isSetFlag(
                    self::XML_PATH_SALES_PDF_INVOICE_PUT_ORDER_ID,
                    \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
                    $order->getStoreId()
                )
            );
                $this->y -= 50;
            /* Add document text and number */
            
            $this->insertDocumentNumber($page, __('Invoice # ') . $invoice->getIncrementId());
            /* Add table */
            $this->_drawHeader($page);
            /* Add body */
            foreach ($invoice->getAllItems() as $item) {
                if ($item->getOrderItem()->getParentItem()) {
                    continue;
                }
                /* Draw item */
                $this->_drawItem($item, $page, $order);
                $page = end($pdf->pages);
            }
            /* Add totals */
            $this->insertTotals($page, $invoice);
            if ($invoice->getStoreId()) {
                $this->appEmulation->stopEnvironmentEmulation();
            }
        }
        $this->_afterGetPdf();
        return $pdf;
    }    
}

    

2 Answers 2

2

magento 2.4 uses $appEmulation instead of $_localeResolver now and changes it from protected to private, thats why you don't have access to that property in your class.

To make it work you have to implement your own __construct function and and initialise $appEmulation yourself.

/**
 * @var \Magento\Store\Model\App\Emulation
 */
private $appEmulation;

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\Store\Model\App\Emulation $appEmulation,
    array $data = []
) {
    $this->appEmulation = $appEmulation;

    parent::__construct(
        $paymentData,
        $string,
        $scopeConfig,
        $filesystem,
        $pdfConfig,
        $pdfTotalFactory,
        $pdfItemsFactory,
        $localeDate,
        $inlineTranslation,
        $addressRenderer,
        $storeManager,
        $appEmulation,
        $data
    );
}
0

I ran into this same problem while extending the Creditmemo.php class. I got it to work now, it might not be best practice but at least it's functional. You won't need to overwrite the extended class' constructor this way.

At the top of your file, make sure you:

use Magento\Framework\App\ObjectManager;
use Magento\Store\Model\App\Emulation;

And then use the class wherever you need it using the objectmanager:

$appEmulation = ObjectManager::getInstance()->get(Emulation::class);
$appEmulation->doYourStuff();

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.