# easy-invoice/2.4.1/includes/Helpers/PreviewOverlay.php

Easy Invoice – Invoice Generator, PDF Quotes &amp; Payments, version 2.4.1. 89 lines.

- Page: https://pluginprobe.com/plugins/easy-invoice/2.4.1/code/includes/Helpers/PreviewOverlay.php
- Raw: https://pluginprobe.com/plugins/easy-invoice/2.4.1/raw/includes/Helpers/PreviewOverlay.php
- Modified: 2026-09-15T12:31:20+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/easy-invoice/2.4.1/code/includes/Helpers/PreviewOverlay.php#L10-L20`.

```php
<?php
/**
 * Overlay the builder's unsaved form values on a document model so the
 * live preview shows what is being typed, not what was last saved.
 *
 * @package EasyInvoice
 */

namespace EasyInvoice\Helpers;

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class PreviewOverlay {

    /**
     * @param object $model     Invoice or Quote model (may be empty/new).
     * @param string $form_data URL-encoded form serialisation from the builder.
     * @param string $type      'invoice' or 'quote'.
     * @return object The same model, with the posted values applied.
     */
    public static function apply( $model, string $form_data, string $type = 'invoice' ) {
        if ( '' === $form_data || ! is_object( $model ) ) {
            return $model;
        }
        parse_str( $form_data, $data );
        $data = wp_unslash( $data );
        if ( ! is_array( $data ) ) {
            return $model;
        }
        // Both models strip the same prefix in setMetaData().
        $prefix = '_easy_invoice_';
        $scalar = [ 'title', 'number', 'issue_date', 'due_date', 'expiry_date', 'notes', 'terms', 'description', 'footer_text', 'status',
                    'discount_type', 'discount_value', 'discount_calculation_method', 'tax_enabled', 'tax_rate', 'prices_include_tax',
                    'currency_code', 'customer_name', 'customer_email', 'customer_address', 'customer_vat_number', 'customer_country', 'client_id' ];
        foreach ( $scalar as $key ) {
            if ( ! array_key_exists( $key, $data ) ) {
                continue;
            }
            $value = is_scalar( $data[ $key ] ) ? sanitize_textarea_field( (string) $data[ $key ] ) : '';
            if ( is_callable( [ $model, 'setMetaData' ] ) ) {
                $model->setMetaData( $prefix . $key, $value );
            }
        }
        // A checkbox that is absent from the serialisation is unchecked.
        if ( ! array_key_exists( 'tax_enabled', $data ) && is_callable( [ $model, 'setMetaData' ] ) ) {
            $model->setMetaData( $prefix . 'tax_enabled', '0' );
        }
        if ( ! empty( $data['items'] ) && is_array( $data['items'] ) ) {
            $items = [];
            foreach ( $data['items'] as $row ) {
                if ( ! is_array( $row ) ) {
                    continue;
                }
                $name = sanitize_text_field( (string) ( $row['title'] ?? $row['name'] ?? '' ) );
                $qty  = (float) ( $row['quantity'] ?? 0 );
                $price = (float) str_replace( ',', '', (string) ( $row['price'] ?? 0 ) );
                if ( '' === $name && 0.0 === $qty && 0.0 === $price ) {
                    continue;
                }
                $items[] = [
                    'name'             => $name,
                    'title'            => $name,
                    'description'      => sanitize_textarea_field( (string) ( $row['description'] ?? '' ) ),
                    'quantity'         => $qty,
                    'price'            => $price,
                    'amount'           => round( $qty * $price, 2 ),
                    'total'            => round( $qty * $price, 2 ),
                    // The form is posted serialised, so an unchecked box is simply absent —
                    // absent means not taxable, as it does when the invoice is saved.
                    'taxable'          => ! empty( $row['taxable'] ) && '0' !== (string) $row['taxable'] ? '1' : '0',
                    'adjust_percentage' => (float) ( $row['adjust_percentage'] ?? $row['adjust'] ?? 0 ),
                ];
            }
            if ( is_callable( [ $model, 'setItems' ] ) ) {
                $model->setItems( $items );
            }
        }
        if ( ! empty( $data['client_id'] ) && is_callable( [ $model, 'populateClientInfo' ] ) ) {
            $model->populateClientInfo();
        }
        if ( is_callable( [ $model, 'calculateTotals' ] ) ) {
            $model->calculateTotals();
        }
        return $model;
    }
}

```
