# easy-invoice/2.1.2/includes/Models/InvoiceItem.php

Easy Invoice – Invoice Generator, PDF Quotes &amp; Payments, version 2.1.2. 260 lines.

- Page: https://pluginprobe.com/plugins/easy-invoice/2.1.2/code/includes/Models/InvoiceItem.php
- Raw: https://pluginprobe.com/plugins/easy-invoice/2.1.2/raw/includes/Models/InvoiceItem.php
- Modified: 2025-08-14T09:51:16+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.1.2/code/includes/Models/InvoiceItem.php#L10-L20`.

```php
<?php
/**
 * Invoice Item Model
 *
 * @package     EasyInvoice
 * @author      Your Name
 * @copyright   Copyright (c) 2023, Your Company
 * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
 * @since       1.0.0
 */

namespace EasyInvoice\Models;

use WP_Post;

/**
 * InvoiceItem Class
 * 
 * Represents an invoice item.
 */
class InvoiceItem {
    /**
     * Item ID
     *
     * @var int
     */
    private $id;

    /**
     * Invoice ID
     *
     * @var int
     */
    private $invoice_id;

    /**
     * Dynamic data storage for all fields
     *
     * @var array
     */
    private $data = [];

    /**
     * Modified flag
     *
     * @var bool
     */
    private $is_modified = false;

    /**
     * Whether this item is based on a post
     *
     * @var bool
     */
    private $is_post = false;

    /**
     * Constructor
     *
     * @param WP_Post|array $data The item data (WP_Post object or array)
     */
    public function __construct($data) {
        $this->data = $data;
        
        if ($data instanceof \WP_Post) {
            $this->is_post = true;
            $this->id = $data->ID;
        } elseif (is_array($data)) {
            $this->is_post = false;
            $this->id = isset($data['id']) ? intval($data['id']) : 0;
        }
    }

    /**
     * Magic method to get dynamic properties
     *
     * @since 1.0.0
     * @param string $name Property name
     * @return mixed Property value
     */
    public function __get($name) {
        // Handle special properties
        if ($name === 'id') {
            return $this->id;
        }
        
        // Handle name/title compatibility
        if ($name === 'name' && empty($this->data[$name]) && !empty($this->data['title'])) {
            return $this->data['title'];
        }
        if ($name === 'title' && empty($this->data[$name]) && !empty($this->data['name'])) {
            return $this->data['name'];
        }
        
        // Return from dynamic data array
        return $this->data[$name] ?? null;
    }

    /**
     * Magic method to set dynamic properties
     *
     * @since 1.0.0
     * @param string $name Property name
     * @param mixed $value Property value
     */
    public function __set($name, $value) {
        // Handle special properties
        if ($name === 'id') {
            $this->id = $value;
            return;
        }
        
        // Store in dynamic data array
        $this->data[$name] = $value;
        $this->is_modified = true;
    }

    /**
     * Magic method to check if property exists
     *
     * @since 1.0.0
     * @param string $name Property name
     * @return bool
     */
    public function __isset($name) {
        if ($name === 'id') {
            return isset($this->id);
        }
        
        return isset($this->data[$name]);
    }

    /**
     * Dynamic getter method
     *
     * @since 1.0.0
     * @param string $name Method name
     * @param array $arguments Method arguments
     * @return mixed
     */
    public function __call($name, $arguments) {
        // Handle getter methods (getFieldName)
        if (strpos($name, 'get') === 0) {
            $field_name = $this->camelCaseToSnakeCase(substr($name, 3)); // Remove 'get' prefix
            
            // Special handling for getName() to check both 'name' and 'title' fields
            if ($field_name === 'name') {
                if (!empty($this->data['name'])) {
                    return $this->data['name'];
                } elseif (!empty($this->data['title'])) {
                    return $this->data['title'];
                }
                return null;
            }
            
            return $this->__get($field_name);
        }
        
        // Handle setter methods (setFieldName)
        if (strpos($name, 'set') === 0) {
            $field_name = $this->camelCaseToSnakeCase(substr($name, 3)); // Remove 'set' prefix
            $value = $arguments[0] ?? null;
            $this->__set($field_name, $value);
            return null;
        }
        
        // Handle isset methods (isFieldName)
        if (strpos($name, 'is') === 0) {
            $field_name = $this->camelCaseToSnakeCase(substr($name, 2)); // Remove 'is' prefix
            return (bool) $this->__get($field_name);
        }
        
        // Handle has methods (hasFieldName)
        if (strpos($name, 'has') === 0) {
            $field_name = $this->camelCaseToSnakeCase(substr($name, 3)); // Remove 'has' prefix
            return !empty($this->__get($field_name));
        }
        
        throw new \BadMethodCallException("Method $name does not exist");
    }

    /**
     * Convert camelCase to snake_case
     *
     * @since 1.0.0
     * @param string $camelCase
     * @return string
     */
    private function camelCaseToSnakeCase($camelCase) {
        return strtolower(preg_replace('/(?<!^)[A-Z]/', '_$0', $camelCase));
    }

    /**
     * Get all data as array
     *
     * @since 1.0.0
     * @return array
     */
    public function toArray(): array {
        $data = $this->data;
        $data['id'] = $this->id;
        // Ensure taxable field is properly set as a boolean
        $data['taxable'] = $this->isTaxable();
        return $data;
    }

    /**
     * Get data array
     *
     * @since 1.0.0
     * @return array
     */
    public function getData(): array {
        return $this->data;
    }

    // Essential methods only
    public function getId(): int { return $this->id; }
    public function setId(int $id): void { $this->id = $id; }
    public function isDirty(): bool { return $this->is_modified; }
    public function resetDirty() { $this->is_modified = false; return $this; }

    /**
     * Get the calculated amount for this item
     *
     * @since 1.0.0
     * @return float The calculated amount
     */
    public function getAmount(): float {
        $quantity = floatval($this->data['quantity'] ?? 1);
        $price = floatval($this->data['price'] ?? 0);
        $adjust_percentage = floatval($this->data['adjust_percentage'] ?? 0);
        
        // Calculate base total
        $base_total = $quantity * $price;
        
        // Apply adjustment percentage if any
        if ($adjust_percentage != 0) {
            $base_total = $base_total * (1 + $adjust_percentage / 100);
        }
        
        return $base_total;
    }

    /**
     * Check if the item is taxable
     *
     * @since 1.0.0
     * @return bool
     */
    public function isTaxable(): bool {
        // Convert various values to boolean
        $value = $this->data['taxable'] ?? true;
        if (is_string($value)) {
            $value = strtolower($value);
            return $value === '1' || $value === 'true' || $value === 'yes' || $value === 'on';
        }
        return (bool) $value;
    }
} 
```
