- Added comprehensive AI Assistant system (aiassist/ directory): * Vector search and embedding capabilities * Typebot proxy integration * Elastic search functionality * Message classification and chat history * MCP proxy for external integrations - Implemented Court Status API (GetCourtStatus.php): * Real-time court document status checking * Integration with external court systems * Comprehensive error handling and logging - Enhanced S3 integration: * Improved file backup system with metadata * Batch processing capabilities * Enhanced error logging and recovery * Copy operations with URL fixing - Added Telegram contact creation API - Improved error logging across all modules - Enhanced callback system for AI responses - Extensive backup file storage with timestamps - Updated documentation and README files - File storage improvements: * Thousands of backup files with proper metadata * Fix operations for broken file references * Project-specific backup and recovery systems * Comprehensive file integrity checking Total: 26,461+ files added/modified including AWS SDK, vendor dependencies, and extensive backup system.
2290 lines
97 KiB
PHP
2290 lines
97 KiB
PHP
<?php
|
|
$memory_limit = substr(ini_get("memory_limit"), 0, -1);
|
|
if ($memory_limit < 256) {
|
|
ini_set("memory_limit", "256M");
|
|
}
|
|
|
|
class PDFMaker_PDFContent_Model extends PDFMaker_PDFContentUtils_Model
|
|
{
|
|
public $PDFMakerCFArray = [];
|
|
public $PDFMakerCFArrayALL = [];
|
|
public static $pagebreak;
|
|
public static $bridge2mpdf = array();
|
|
private static $is_inventory_module = [];
|
|
private static $templateid;
|
|
private static $module;
|
|
private static $language;
|
|
private static $focus;
|
|
private static $db;
|
|
private static $mod_strings;
|
|
private static $def_charset;
|
|
private static $site_url;
|
|
private static $decimal_point;
|
|
private static $thousands_separator;
|
|
private static $decimals;
|
|
private static $truncate_zero;
|
|
private static $disable_export_edit;
|
|
private static $rowbreak;
|
|
private static $ignored_picklist_values = array();
|
|
private static $header;
|
|
private static $footer;
|
|
private static $body;
|
|
private static $content;
|
|
private static $filename;
|
|
private static $pdf_password;
|
|
private static $watermark_text;
|
|
private static $templatename;
|
|
private static $type;
|
|
private static $section_sep = "&#%ITS%%%@@@%%%ITS%#&";
|
|
private static $rep;
|
|
private static $inventory_table_array = array("PurchaseOrder" => "vtiger_purchaseorder", "SalesOrder" => "vtiger_salesorder", "Quotes" => "vtiger_quotes", "Invoice" => "vtiger_invoice", "Issuecards" => "vtiger_issuecards", "Receiptcards" => "vtiger_receiptcards", "Creditnote" => "vtiger_creditnote", "StornoInvoice" => "vtiger_stornoinvoice");
|
|
private static $inventory_id_array = array("PurchaseOrder" => "purchaseorderid", "SalesOrder" => "salesorderid", "Quotes" => "quoteid", "Invoice" => "invoiceid", "Issuecards" => "issuecardid", "Receiptcards" => "receiptcardid", "Creditnote" => "creditnote_id", "StornoInvoice" => "stornoinvoice_id");
|
|
private static $org_colsOLD = array("organizationname" => "NAME", "address" => "ADDRESS", "city" => "CITY", "state" => "STATE", "code" => "ZIP", "country" => "COUNTRY", "phone" => "PHONE", "fax" => "FAX", "website" => "WEBSITE", "logo" => "LOGO");
|
|
private static $relBlockModules = array();
|
|
|
|
/** @var PDFMaker_PDFMaker_Model */
|
|
public $PDFMaker;
|
|
|
|
/** @var PDFMaker_Module_Model */
|
|
public $moduleModel;
|
|
public $skipPageBreaks = false;
|
|
|
|
/**
|
|
* @param int $l_templateid
|
|
* @param string $l_module
|
|
* @param object $l_focus
|
|
* @param string $l_language
|
|
*/
|
|
public function __construct($l_templateid, $l_module, $l_focus, $l_language)
|
|
{
|
|
if (!defined('LOGO_PATH')) {
|
|
define('LOGO_PATH', 'test/logo/');
|
|
}
|
|
|
|
PDFMaker_Debugger_Model::GetInstance()->Init();
|
|
|
|
self::$db = PearDatabase::getInstance();
|
|
self::$def_charset = vglobal('default_charset');
|
|
|
|
$this->retrievePDFMakerModel();
|
|
$this->retrieveModuleModel();
|
|
$this->setLanguage($l_language);
|
|
$this->setTemplateId($l_templateid);
|
|
|
|
self::$module = $l_module;
|
|
self::$focus = $l_focus;
|
|
|
|
$this->retrieveModStrings();
|
|
$this->getTemplateData();
|
|
$this->getIgnoredPicklistValues();
|
|
|
|
self::$bridge2mpdf['record'] = self::$focus->id;
|
|
self::$bridge2mpdf['templateid'] = self::$templateid;
|
|
self::$rowbreak = '<rowbreak />';
|
|
self::$is_inventory_module[self::$module] = $this->isInventoryModule(self::$module);
|
|
}
|
|
|
|
/**
|
|
* @param int $templateId
|
|
* @param string $moduleName
|
|
* @param object $focus
|
|
* @param string $language
|
|
* @return PDFMaker_PDFContent_Model
|
|
*/
|
|
public static function getInstance($templateId, $moduleName, $focus, $language)
|
|
{
|
|
return new self($templateId, $moduleName, $focus, $language);
|
|
}
|
|
|
|
public function retrieveModStrings()
|
|
{
|
|
$mod_strings_array = Vtiger_Language_Handler::getModuleStringsFromFile(self::$language, self::$module);
|
|
|
|
self::$mod_strings = $mod_strings_array['languageStrings'];
|
|
}
|
|
|
|
public function setTemplateId($value)
|
|
{
|
|
self::$templateid = $value;
|
|
|
|
vglobal('PDFMaker_template_id', $value);
|
|
}
|
|
|
|
public function setLanguage($value)
|
|
{
|
|
self::$language = $value;
|
|
|
|
$current_user = Users_Record_Model::getCurrentUserModel();
|
|
$current_user->set('language', $value);
|
|
}
|
|
|
|
public function retrievePDFMakerModel()
|
|
{
|
|
$this->PDFMaker = new PDFMaker_PDFMaker_Model();
|
|
}
|
|
|
|
public function retrieveModuleModel()
|
|
{
|
|
$this->moduleModel = Vtiger_Module_Model::getInstance('PDFMaker');
|
|
}
|
|
|
|
public function getPDFMakerModel()
|
|
{
|
|
if (!$this->PDFMaker) {
|
|
$this->retrievePDFMakerModel();
|
|
}
|
|
|
|
return $this->PDFMaker;
|
|
}
|
|
|
|
public function getModuleModel()
|
|
{
|
|
if (!$this->moduleModel) {
|
|
$this->retrieveModuleModel();
|
|
}
|
|
|
|
return $this->moduleModel;
|
|
}
|
|
|
|
private function getTemplateData()
|
|
{
|
|
self::$site_url = trim(vglobal('site_URL'), "/");
|
|
|
|
$result = self::$db->pquery("SELECT vtiger_pdfmaker.*, vtiger_pdfmaker_settings.* FROM vtiger_pdfmaker LEFT JOIN vtiger_pdfmaker_settings ON vtiger_pdfmaker_settings.templateid = vtiger_pdfmaker.templateid WHERE vtiger_pdfmaker.templateid=?", array(self::$templateid));
|
|
$data = self::$db->fetch_array($result);
|
|
|
|
self::$decimal_point = html_entity_decode($data["decimal_point"], ENT_QUOTES);
|
|
self::$thousands_separator = html_entity_decode(($data["thousands_separator"] != "sp" ? $data["thousands_separator"] : " "), ENT_QUOTES);
|
|
self::$decimals = $data["decimals"];
|
|
self::$truncate_zero = $data['truncate_zero'];
|
|
self::$disable_export_edit = $data['disable_export_edit'];
|
|
|
|
foreach (array("header", "footer") as $stype) {
|
|
if (!empty($data[$stype . 'id']) && $data[$stype . 'id'] != "0") {
|
|
$data[$stype] = $this->moduleModel->getTemplateBlockContent($data[$stype . 'id']);
|
|
}
|
|
}
|
|
|
|
self::$header = $data["header"];
|
|
self::$footer = $data["footer"];
|
|
|
|
|
|
self::$body = $data["body"];
|
|
self::$filename = $data["file_name"];
|
|
self::$pdf_password = $data["pdf_password"];
|
|
self::$watermark_text = $data["watermark_text"];
|
|
|
|
self::$templatename = $data["filename"];
|
|
|
|
$this->retrievePageBreak($data);
|
|
}
|
|
|
|
public function getPageBreakFormat($data)
|
|
{
|
|
$formatPB = $data['format'];
|
|
|
|
if (0 < strpos($formatPB, ';')) {
|
|
$tmpArr = explode(';', $formatPB);
|
|
$formatPB = $tmpArr[0] . 'mm ' . $tmpArr[1] . 'mm';
|
|
} elseif ($data['orientation'] == 'landscape') {
|
|
$formatPB .= "-L";
|
|
}
|
|
|
|
return $formatPB;
|
|
}
|
|
|
|
private function getIgnoredPicklistValues()
|
|
{
|
|
$result = self::$db->pquery("SELECT value FROM vtiger_pdfmaker_ignorepicklistvalues", array());
|
|
while ($row = self::$db->fetchByAssoc($result)) {
|
|
self::$ignored_picklist_values[] = $row["value"];
|
|
}
|
|
}
|
|
|
|
public function replaceDates()
|
|
{
|
|
$currentUser = Users_Record_Model::getCurrentUserModel();
|
|
$hour = '24' == $currentUser->get('hour_format') ? date('H') : date('h');
|
|
|
|
self::$rep['##DD-MM-YYYY##'] = date('d-m-Y');
|
|
self::$rep['##DD.MM.YYYY##'] = date('d.m.Y');
|
|
self::$rep['##MM-DD-YYYY##'] = date('m-d-Y');
|
|
self::$rep['##YYYY-MM-DD##'] = date('Y-m-d');
|
|
self::$rep['##HH:II:SS##'] = $hour . date(':i:s');
|
|
self::$rep['##HH:II##'] = $hour . date(':i');
|
|
self::$rep["##YYYY##"] = date('Y');
|
|
self::$rep["##MM##"] = date('m');
|
|
self::$rep["##DD##"] = date('d');
|
|
self::$rep["##HH##"] = $hour;
|
|
self::$rep["##II##"] = date('i');
|
|
self::$rep["##SS##"] = date('s');
|
|
}
|
|
|
|
public function getContent()
|
|
{
|
|
PDFMaker_PDFMaker_Model::getSimpleHtmlDomFile();
|
|
$img_root = vglobal('img_root_directory');
|
|
|
|
if (self::$module == 'Calendar') {
|
|
self::$rep = array();
|
|
}
|
|
|
|
self::$content = self::$body;
|
|
self::$content = self::$header . self::$section_sep;
|
|
self::$content .= self::$body . self::$section_sep;
|
|
self::$content .= self::$footer;
|
|
self::$rep['$siteurl$'] = self::$site_url;
|
|
self::$rep[' '] = ' ';
|
|
self::$rep['##PAGE##'] = '{PAGENO}';
|
|
self::$rep['##PAGES##'] = '{nb}';
|
|
$this->replaceDates();
|
|
self::$rep["src='"] = "src='" . $img_root;
|
|
self::$rep["$" . strtoupper(self::$module) . "_CRMID$"] = self::$focus->id;
|
|
self::$rep["%" . strtoupper(self::$module) . "_CRMID%"] = "CRMID";
|
|
$createdtime = new DateTimeField(self::$focus->column_fields['createdtime']);
|
|
$displayValueCreated = $createdtime->getDisplayDateTimeValue();
|
|
$modifiedtime = new DateTimeField(self::$focus->column_fields['modifiedtime']);
|
|
$displayValueModified = $modifiedtime->getDisplayDateTimeValue();
|
|
self::$rep["$" . strtoupper(self::$module) . "_CREATEDTIME_DATETIME$"] = $displayValueCreated;
|
|
self::$rep["$" . strtoupper(self::$module) . "_MODIFIEDTIME_DATETIME$"] = $displayValueModified;
|
|
$this->convertEntityImages();
|
|
$this->replaceContent();
|
|
self::$content = html_entity_decode(self::$content, ENT_QUOTES, self::$def_charset);
|
|
$html = str_get_html(self::$content);
|
|
$page_break_after = $html->find("div[style^=page-break-after]");
|
|
|
|
if (is_array($page_break_after)) {
|
|
foreach ($page_break_after as $div_page_break) {
|
|
$div_page_break->outertext = self::$pagebreak;
|
|
self::$content = $html->save();
|
|
}
|
|
}
|
|
|
|
$page_break_after2 = $html->find("div[style^=PAGE-BREAK-AFTER]");
|
|
|
|
if (is_array($page_break_after2)) {
|
|
foreach ($page_break_after2 as $div_page_break) {
|
|
$div_page_break->outertext = self::$pagebreak;
|
|
self::$content = $html->save();
|
|
}
|
|
}
|
|
|
|
$this->convertRelatedModule();
|
|
$this->convertRelatedBlocks();
|
|
$this->replaceFieldsToContent(self::$module, self::$focus);
|
|
|
|
if (self::$module == "Calendar") {
|
|
$this->replaceFieldsToContent("Events", self::$focus);
|
|
}
|
|
|
|
$this->convertInventoryModules();
|
|
$this->retrieveAssignedUser();
|
|
self::$content = $this->convertListViewBlock(self::$content);
|
|
$this->handleRowbreak();
|
|
$this->replaceUserCompanyFields();
|
|
$this->replaceLabels();
|
|
self::$content = $this->replaceBarcode(self::$content);
|
|
self::$content = $this->fixImg(self::$content);
|
|
|
|
if (strtoupper(self::$def_charset) != "UTF-8") {
|
|
self::$content = iconv(self::$def_charset, "UTF-8//TRANSLIT", self::$content);
|
|
}
|
|
|
|
$this->convertHideTR('BEFORE');
|
|
$this->replaceCustomFunctions();
|
|
$this->convertHideTR();
|
|
$this->replaceSignature();
|
|
$this->replacePageBreak();
|
|
$PDF_content = array();
|
|
list($PDF_content["header"], $PDF_content["body"], $PDF_content["footer"]) = explode(
|
|
self::$section_sep,
|
|
self::$content
|
|
);
|
|
|
|
return $PDF_content;
|
|
}
|
|
|
|
public function retrieveAssignedUser()
|
|
{
|
|
if (empty(self::$focus->column_fields['assigned_user_id'])) {
|
|
$result = self::$db->pquery('SELECT smownerid FROM vtiger_crmentity WHERE crmid=?', array(self::$focus->id));
|
|
|
|
self::$focus->column_fields['assigned_user_id'] = self::$db->query_result($result, 0, 'smownerid');
|
|
}
|
|
}
|
|
|
|
public function replacePageBreak()
|
|
{
|
|
if ($this->strContain(self::$content, PDFMaker_PageBreak_Model::PAGE_BREAK_TAG)) {
|
|
$pageBreak = PDFMaker_PageBreak_Model::getInstance(self::$content);
|
|
|
|
if (!$this->skipPageBreaks) {
|
|
$pageBreak->setPageBreak($this->getPageBreak());
|
|
} else {
|
|
$pageBreak->setPageBreak($pageBreak::PAGE_BREAK_TAG);
|
|
}
|
|
|
|
$pageBreak->updateContent();
|
|
|
|
self::$content = $pageBreak->getContent();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $value
|
|
* @param string $search
|
|
* @return bool
|
|
*/
|
|
public function strContain($value, $search)
|
|
{
|
|
return false !== stripos($value, $search);
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getSignature()
|
|
{
|
|
$signHtml = vglobal('ITS4YouSignatureHTML');
|
|
|
|
if ($signHtml) {
|
|
return $signHtml;
|
|
}
|
|
|
|
$settings = $this->getSettings();
|
|
$signatureImage = vglobal('ITS4YouSignatureImage');
|
|
$image = !empty($signatureImage) ? $signatureImage : $this->getEmptySignature();
|
|
|
|
return $this->getSignatureImage($image, $settings['signature_width'], $settings['signature_height']);
|
|
}
|
|
|
|
public function getEmptySignature()
|
|
{
|
|
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/3PfWwAJWgOlFi1RWAAAAABJRU5ErkJggg==';
|
|
}
|
|
|
|
public function getSignatureImage($src, $width, $height)
|
|
{
|
|
$width = empty($width) ? 150 : (int)$width;
|
|
$height = empty($height) ? 60 : (int)$height;
|
|
|
|
return $src ? '<img width="' . $width . '" height="' . $height . '" src="' . $src . '" alt="Signature">' : 'The Signature is missing or has been deleted';
|
|
}
|
|
|
|
public function retrieveConfirmSignatures()
|
|
{
|
|
/**
|
|
* confirm 1 = replace with images
|
|
* confirm 2 = replace with placeholder
|
|
* confirm 3 = edit
|
|
*/
|
|
$confirm = (int)vglobal('ITS4YouSignatureConfirm');
|
|
|
|
if (3 !== $confirm) {
|
|
$string = self::$body;
|
|
$regex = '/\$PDF\_SIGNATURE\_([A-Z]*)\_([0-9]*)\$/m';
|
|
|
|
preg_match_all($regex, $string, $matches, PREG_SET_ORDER, 0);
|
|
|
|
foreach ($matches as $match) {
|
|
list($variable, $type, $record) = $match;
|
|
|
|
$recordModel = PDFMaker_Signatures_Model::getInstanceById($record);
|
|
$image = 1 === $confirm ? $recordModel->getImage() : $this->getEmptySignature();
|
|
|
|
self::$rep[$variable] = $this->getSignatureImage($image, $recordModel->get('width'), $recordModel->get('height'));
|
|
}
|
|
}
|
|
}
|
|
|
|
public function setBody($value)
|
|
{
|
|
self::$body = $value;
|
|
}
|
|
|
|
public function replaceSignature()
|
|
{
|
|
self::$rep['$PDF_SIGNATURE$'] = $this->getSignature();
|
|
|
|
$this->retrieveConfirmSignatures();
|
|
$this->replaceContent();
|
|
}
|
|
|
|
private function convertEntityImages()
|
|
{
|
|
switch (self::$module) {
|
|
case "Contacts":
|
|
self::$rep["$" . "CONTACTS_IMAGENAME$"] = $this->getContactImage(self::$focus->id, self::$site_url);
|
|
break;
|
|
case "Products":
|
|
self::$rep['$PRODUCTS_IMAGENAME$'] = $this->getProductImage(self::$focus->id, self::$site_url);
|
|
self::$rep['$PRODUCT_IMAGE$'] = self::$rep['$PRODUCTS_IMAGENAME$'];
|
|
break;
|
|
}
|
|
}
|
|
|
|
private function replaceContent()
|
|
{
|
|
if (!empty(self::$rep)) {
|
|
self::$content = str_replace(array_keys(self::$rep), self::$rep, self::$content);
|
|
|
|
self::$filename = str_replace(array_keys(self::$rep), self::$rep, self::$filename);
|
|
self::$pdf_password = str_replace(array_keys(self::$rep), self::$rep, self::$pdf_password);
|
|
self::$watermark_text = str_replace(array_keys(self::$rep), self::$rep, self::$watermark_text);
|
|
|
|
self::$rep = array();
|
|
}
|
|
}
|
|
|
|
private function convertRelatedModule()
|
|
{
|
|
$v = "vtiger_current_version";
|
|
$vcv = vglobal($v);
|
|
$field_inf = "_fieldinfo_cache";
|
|
$module_tabid = getTabId(self::$module);
|
|
$Query_Parr = array('3', '64', $module_tabid);
|
|
$sql = "SELECT fieldid, fieldname, uitype, columnname FROM vtiger_field WHERE (displaytype != ? OR fieldid = ?) AND tabid";
|
|
if (self::$module == "Calendar") {
|
|
$Query_Parr[] = getTabId("Events");
|
|
$sql .= " IN ( ?, ? ) GROUP BY fieldname";
|
|
} else {
|
|
$sql .= " = ?";
|
|
}
|
|
|
|
$result = self::$db->pquery($sql, $Query_Parr);
|
|
$num_rows = self::$db->num_rows($result);
|
|
|
|
if ($num_rows > 0) {
|
|
while ($row = self::$db->fetch_array($result)) {
|
|
$fieldModel = Vtiger_Field_Model::getInstance($row["fieldid"]);
|
|
$columnname = $row["columnname"];
|
|
$fk_record = self::$focus->column_fields[$row["fieldname"]];
|
|
$related_module = $this->getUITypeRelatedModule($row["uitype"], $fk_record);
|
|
|
|
if ($fieldModel) {
|
|
$references = array_merge(array($related_module), $fieldModel->getReferenceList());
|
|
|
|
if (!empty($references)) {
|
|
foreach ($references as $related_module) {
|
|
if (!PDFMaker_Module_Model::isModuleActive($related_module)) {
|
|
continue;
|
|
}
|
|
$displayValueModified = $displayValueCreated = $related_module_id = "";
|
|
$tabid = getTabId($related_module);
|
|
$temp = &VTCacheUtils::$$field_inf;
|
|
unset($temp[$tabid]);
|
|
$focus2 = CRMEntity::getInstance($related_module);
|
|
if ($fk_record != "" && $fk_record != "0") {
|
|
if ($related_module == "Users") {
|
|
$control_sql = "vtiger_users WHERE id=";
|
|
} else {
|
|
$control_sql = "vtiger_crmentity WHERE crmid=";
|
|
}
|
|
$result_delete = self::$db->pquery("SELECT deleted FROM " . $control_sql . "? AND deleted=0", array($fk_record));
|
|
if (self::$db->num_rows($result_delete) > 0) {
|
|
$focus2->retrieve_entity_info($fk_record, $related_module);
|
|
$related_module_id = $focus2->id = $fk_record;
|
|
|
|
if ($vcv == '5.2.1') {
|
|
$displayValueCreated = getDisplayDate($focus2->column_fields['createdtime']);
|
|
$displayValueModified = getDisplayDate($focus2->column_fields['modifiedtime']);
|
|
} else {
|
|
if (!empty($focus2->column_fields['createdtime'])) {
|
|
$createdtime = new DateTimeField($focus2->column_fields['createdtime']);
|
|
$displayValueCreated = $createdtime->getDisplayDateTimeValue();
|
|
}
|
|
if (!empty($focus2->column_fields['modifiedtime'])) {
|
|
$modifiedtime = new DateTimeField($focus2->column_fields['modifiedtime']);
|
|
$displayValueModified = $modifiedtime->getDisplayDateTimeValue();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
self::$rep["$" . "R_" . strtoupper($columnname) . "_CRMID$"] = $related_module_id;
|
|
self::$rep["$" . "R_" . strtoupper($columnname) . "_CREATEDTIME_DATETIME$"] = $displayValueCreated;
|
|
self::$rep["$" . "R_" . strtoupper($columnname) . "_MODIFIEDTIME_DATETIME$"] = $displayValueModified;
|
|
|
|
if ($related_module != "Users") {
|
|
self::$rep["$" . "R_" . strtoupper($related_module) . "_CRMID$"] = $related_module_id;
|
|
self::$rep["$" . "R_" . strtoupper($related_module) . "_CREATEDTIME_DATETIME$"] = $displayValueCreated;
|
|
self::$rep["$" . "R_" . strtoupper($related_module) . "_MODIFIEDTIME_DATETIME$"] = $displayValueModified;
|
|
}
|
|
if (isset($related_module)) {
|
|
$entityImg = "";
|
|
switch ($related_module) {
|
|
case "Contacts":
|
|
$entityImg = $this->getContactImage($related_module_id, self::$site_url);
|
|
break;
|
|
case "Products":
|
|
$entityImg = $this->getProductImage($related_module_id, self::$site_url);
|
|
break;
|
|
}
|
|
|
|
if ($related_module != "Users") {
|
|
self::$rep["$" . "R_" . strtoupper($related_module) . "_IMAGENAME$"] = $entityImg;
|
|
}
|
|
self::$rep["$" . "R_" . strtoupper($columnname) . "_IMAGENAME$"] = $entityImg;
|
|
}
|
|
$this->replaceContent();
|
|
if ($related_module != "Users") {
|
|
$this->replaceFieldsToContent($related_module, $focus2, true);
|
|
}
|
|
$this->replaceFieldsToContent($related_module, $focus2, $columnname);
|
|
$this->replaceInventoryDetailsBlock($related_module, $focus2, $columnname);
|
|
|
|
unset($focus2);
|
|
}
|
|
}
|
|
}
|
|
|
|
$fieldModRel = $this->GetFieldModuleRel();
|
|
|
|
if ($row["uitype"] == "68") {
|
|
$fieldModRel[$row["fieldid"]][] = "Contacts";
|
|
$fieldModRel[$row["fieldid"]][] = "Accounts";
|
|
}
|
|
|
|
if (isset($fieldModRel[$row["fieldid"]])) {
|
|
foreach ($fieldModRel[$row["fieldid"]] as $idx => $relMod) {
|
|
if (!PDFMaker_Module_Model::isModuleActive($relMod) || $relMod == $related_module) {
|
|
continue;
|
|
}
|
|
|
|
$tmpTabId = getTabId($relMod);
|
|
$temp = &VTCacheUtils::$$field_inf;
|
|
unset($temp[$tmpTabId]);
|
|
if (file_exists("modules/" . $relMod . "/" . $relMod . ".php")) {
|
|
$tmpFocus = CRMEntity::getInstance($relMod);
|
|
|
|
|
|
if ($related_module != "Users") {
|
|
self::$rep["$" . "R_" . strtoupper($relMod) . "_CRMID$"] = "";
|
|
self::$rep["$" . "R_" . strtoupper($relMod) . "_CREATEDTIME_DATETIME$"] = "";
|
|
self::$rep["$" . "R_" . strtoupper($relMod) . "_MODIFIEDTIME_DATETIME$"] = "";
|
|
$this->replaceFieldsToContent($relMod, $tmpFocus, true);
|
|
}
|
|
|
|
self::$rep["$" . "R_" . strtoupper($columnname) . "_CRMID$"] = "";
|
|
self::$rep["$" . "R_" . strtoupper($columnname) . "_CREATEDTIME_DATETIME$"] = "";
|
|
self::$rep["$" . "R_" . strtoupper($columnname) . "_MODIFIEDTIME_DATETIME$"] = "";
|
|
|
|
$this->replaceFieldsToContent($relMod, $tmpFocus, $columnname);
|
|
$this->replaceInventoryDetailsBlock($relMod, $tmpFocus, $columnname);
|
|
unset($tmpFocus);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public function isProductsBlockField($value)
|
|
{
|
|
$productBlockValues = [
|
|
'received',
|
|
'balance',
|
|
'paid',
|
|
'paidamount',
|
|
'openamount',
|
|
];
|
|
|
|
return in_array($value, $productBlockValues);
|
|
}
|
|
|
|
protected $recordExists = array();
|
|
|
|
/**
|
|
* @param bool $record
|
|
* @return bool
|
|
*/
|
|
public function isRecordExists($record)
|
|
{
|
|
if (!isset($this->recordExists[$record])) {
|
|
$this->recordExists[$record] = !empty($record) && isRecordExists($record);
|
|
}
|
|
|
|
return $this->recordExists[$record];
|
|
}
|
|
|
|
protected $userExists = array();
|
|
|
|
public function isUserExists($record)
|
|
{
|
|
if (!isset($this->userExists[$record])) {
|
|
$adb = PearDatabase::getInstance();
|
|
$result = $adb->pquery('SELECT user_name FROM vtiger_users WHERE id=? AND deleted=?',
|
|
[$record, '0']
|
|
);
|
|
|
|
$this->userExists[$record] = !empty($record) && $adb->num_rows($result);
|
|
}
|
|
|
|
return $this->userExists[$record];
|
|
}
|
|
|
|
protected $groupExists = array();
|
|
|
|
public function isGroupExists($record)
|
|
{
|
|
if (!isset($this->groupExists[$record])) {
|
|
$adb = PearDatabase::getInstance();
|
|
$result = $adb->pquery('SELECT groupname FROM vtiger_groups WHERE groupid=?',
|
|
[$record]
|
|
);
|
|
|
|
$this->groupExists[$record] = !empty($record) && $adb->num_rows($result);
|
|
}
|
|
|
|
return $this->groupExists[$record];
|
|
}
|
|
|
|
public function isRecordModelStructure($record, $module = '')
|
|
{
|
|
return $this->isRecordExists($record) ||
|
|
('Users' === $module && $this->isUserExists($record));
|
|
}
|
|
|
|
public function getFieldDisplayValue($field, $inventoryCurrency)
|
|
{
|
|
$fieldValue = $field->get('fieldvalue');
|
|
$fieldName = $field->get('name');
|
|
$fieldDataType = $field->getFieldDataType();
|
|
|
|
switch ($fieldDataType) {
|
|
case 'owner':
|
|
$fieldDisplayValue = getOwnerName($fieldValue);
|
|
break;
|
|
case 'reference':
|
|
$fieldDisplayValue = $field->getEditViewDisplayValue($fieldValue);
|
|
break;
|
|
case 'double':
|
|
case 'percentage':
|
|
$fieldDisplayValue = $this->formatNumberToPDF($fieldValue);
|
|
break;
|
|
case 'currency':
|
|
if (is_numeric($fieldValue) && !$this->isProductsBlockField($fieldName)) {
|
|
if (!$inventoryCurrency) {
|
|
$current_user = Users_Record_Model::getCurrentUserModel();
|
|
$user_currency_data = getCurrencySymbolandCRate($current_user->currency_id);
|
|
$crate = $user_currency_data['rate'];
|
|
} else {
|
|
$crate = $inventoryCurrency['conversion_rate'];
|
|
}
|
|
|
|
$fieldValue = (float)$fieldValue * (float)$crate;
|
|
}
|
|
|
|
$fieldDisplayValue = $this->formatCurrencyToPDF($fieldValue);
|
|
break;
|
|
case 'url':
|
|
$fieldDisplayValue = $fieldValue;
|
|
break;
|
|
case 'picklist':
|
|
$fieldDisplayValue = !empty($fieldValue) ? $this->getTranslatedStringCustom($fieldValue, $field->getModuleName(), self::$language) : '';
|
|
break;
|
|
case 'text':
|
|
$fieldDisplayValue = decode_html($field->getDisplayValue($fieldValue));
|
|
break;
|
|
default:
|
|
$fieldDisplayValue = $field->getDisplayValue($fieldValue);
|
|
break;
|
|
}
|
|
|
|
return $fieldDisplayValue;
|
|
}
|
|
|
|
/**
|
|
* @param string $module
|
|
* @param object $focus
|
|
* @param bool|string $is_related
|
|
* @param bool $inventory_currency
|
|
* @param string $related
|
|
* @return array|bool|void
|
|
*/
|
|
private function replaceFieldsToContent($module, $focus, $is_related = false, $inventory_currency = false, $related = 'R_')
|
|
{
|
|
$current_user = Users_Record_Model::getCurrentUserModel();
|
|
|
|
if (false !== $inventory_currency) {
|
|
$inventory_content = array();
|
|
}
|
|
|
|
$convEntity = 'Events' === $module ? 'Calendar' : $module;
|
|
|
|
if (false === $is_related) {
|
|
$related = '';
|
|
} elseif (true !== $is_related) {
|
|
$convEntity = $is_related;
|
|
}
|
|
|
|
if ($this->isRecordModelStructure($focus->id, $module)) {
|
|
$VtigerDetailViewModel = Vtiger_DetailView_Model::getInstance($module, $focus->id);
|
|
$recordModel = $VtigerDetailViewModel->getRecord();
|
|
$recordStructure = Vtiger_RecordStructure_Model::getInstanceFromRecordModel($recordModel, '');
|
|
} else {
|
|
$moduleModel = Vtiger_Module_Model::getInstance($module);
|
|
$recordStructure = Vtiger_RecordStructure_Model::getInstanceForModule($moduleModel, '');
|
|
}
|
|
|
|
foreach ($recordStructure->getStructure() as $blockFields) {
|
|
foreach ($blockFields as $fieldModel) {
|
|
$fieldName = $fieldModel->get('name');
|
|
$fieldLabel = $fieldModel->get('label');
|
|
$fieldDisplayValue = '';
|
|
|
|
if ($this->isRecordModelStructure($focus->id, $module)) {
|
|
if ('Calendar' === $module) {
|
|
$this->updateCalendarField($fieldModel, $recordModel);
|
|
}
|
|
|
|
$fieldDisplayValue = $this->getFieldDisplayValue($fieldModel, $inventory_currency);
|
|
}
|
|
|
|
self::$rep['%' . $related . strtoupper($convEntity . '_' . $fieldName) . '%'] = vtranslate($fieldLabel, $module);
|
|
self::$rep['%M_' . $fieldLabel . '%'] = vtranslate($fieldLabel, $module);
|
|
|
|
if ($inventory_currency !== false) {
|
|
$inventory_content[strtoupper($module . '_' . $fieldName)] = $fieldDisplayValue;
|
|
} else {
|
|
self::$rep['$' . $related . strtoupper($convEntity . '_' . $fieldName) . '$'] = $fieldDisplayValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->retrieveDisabledFields($module, $related . $convEntity);
|
|
|
|
if ($inventory_currency !== false) {
|
|
return $inventory_content;
|
|
} else {
|
|
$this->replaceContent();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public function retrieveDisabledFields($module, $prefix)
|
|
{
|
|
$result = self::$db->pquery(
|
|
'SELECT fieldname FROM vtiger_field WHERE presence=? AND tabid=?',
|
|
[1, getTabid($module)]
|
|
);
|
|
|
|
while ($row = self::$db->fetchByAssoc($result)) {
|
|
self::$rep['$' . strtoupper($prefix . '_' . $row['fieldname']) . '$'] = '';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $value
|
|
* @return string
|
|
*/
|
|
private function formatNumberToPDF($value)
|
|
{
|
|
$number = '';
|
|
|
|
if (is_numeric($value)) {
|
|
$number = number_format($value, self::$decimals, self::$decimal_point, self::$thousands_separator);
|
|
|
|
if (self::$truncate_zero) {
|
|
$number = rtrim(rtrim($number, '0'), self::$decimal_point);
|
|
}
|
|
}
|
|
|
|
return $number;
|
|
}
|
|
|
|
/**
|
|
* @param string $value
|
|
* @return string
|
|
*/
|
|
private function formatCurrencyToPDF($value)
|
|
{
|
|
$settings = $this->getSettings();
|
|
$number = '';
|
|
|
|
if(is_numeric($value)) {
|
|
if($settings['is_currency']) {
|
|
$thousands = 'sp' === $settings['currency_thousands'] ? ' ' : $settings['currency_thousands'];
|
|
$point = 'sp' === $settings['currency_point'] ? ' ' : $settings['currency_point'];
|
|
$number = number_format($value, $settings['currency'], $point, $thousands);
|
|
} else {
|
|
$number = $this->formatNumberToPDF($value);
|
|
}
|
|
}
|
|
|
|
return $number;
|
|
}
|
|
|
|
private function replaceInventoryDetailsBlock($module, $focus, $is_related = false)
|
|
{
|
|
if (!isset(self::$inventory_table_array[$module])) {
|
|
$this->fillInventoryData($module, $focus);
|
|
}
|
|
if (!isset(self::$inventory_table_array[$module])) {
|
|
return array();
|
|
}
|
|
$prefix = "";
|
|
if ($is_related !== false) {
|
|
$prefix = "R_" . strtoupper($is_related) . "_";
|
|
}
|
|
self::$rep["$" . $prefix . "SUBTOTAL$"] = $this->formatCurrencyToPDF($focus->column_fields["hdnSubTotal"]);
|
|
self::$rep["$" . $prefix . "TOTAL$"] = $this->formatCurrencyToPDF($focus->column_fields["hdnGrandTotal"]);
|
|
|
|
$currencytype = $this->getInventoryCurrencyInfoCustom($module, $focus);
|
|
$currencytype["currency_symbol"] = str_replace("€", "€", $currencytype["currency_symbol"]);
|
|
$currencytype["currency_symbol"] = str_replace("£", "£", $currencytype["currency_symbol"]);
|
|
|
|
self::$rep["$" . $prefix . "CURRENCYNAME$"] = getTranslatedCurrencyString($currencytype["currency_name"]);
|
|
self::$rep["$" . $prefix . "CURRENCYSYMBOL$"] = $currencytype["currency_symbol"];
|
|
self::$rep["$" . $prefix . "CURRENCYCODE$"] = $currencytype["currency_code"];
|
|
self::$rep["$" . $prefix . "ADJUSTMENT$"] = $this->formatCurrencyToPDF($focus->column_fields["txtAdjustment"]);
|
|
|
|
$Products = $this->getInventoryProducts($module, $focus);
|
|
|
|
self::$rep["$" . $prefix . "TOTALWITHOUTVAT$"] = $Products["TOTAL"]["TOTALWITHOUTVAT"];
|
|
self::$rep["$" . $prefix . "VAT$"] = $Products["TOTAL"]["TAXTOTAL"];
|
|
|
|
if('individual' === $Products['TOTAL']['TAXTYPE']) {
|
|
self::$rep["$" . $prefix . "VATPERCENT$"] = '$VATPERCENT_INDIVIDUAL$';
|
|
} else {
|
|
self::$rep["$" . $prefix . "VATPERCENT$"] = $Products["TOTAL"]["TAXTOTALPERCENT"];
|
|
}
|
|
|
|
self::$rep["$" . $prefix . "TOTALWITHVAT$"] = $Products["TOTAL"]["TOTALWITHVAT"];
|
|
self::$rep["$" . $prefix . "SHTAXAMOUNT$"] = $Products["TOTAL"]["SHTAXAMOUNT"];
|
|
self::$rep["$" . $prefix . "SHTAXTOTAL$"] = $Products["TOTAL"]["SHTAXTOTAL"];
|
|
self::$rep["$" . $prefix . "DEDUCTEDTAXESTOTAL$"] = $Products["TOTAL"]["DEDUCTEDTAXESTOTAL"];
|
|
self::$rep["$" . $prefix . "TOTALDISCOUNT$"] = $Products["TOTAL"]["FINALDISCOUNT"];
|
|
self::$rep["$" . $prefix . "TOTALDISCOUNTPERCENT$"] = $Products["TOTAL"]["FINALDISCOUNTPERCENT"];
|
|
self::$rep["$" . $prefix . "TOTALAFTERDISCOUNT$"] = $Products["TOTAL"]["TOTALAFTERDISCOUNT"];
|
|
self::$rep["$" . $prefix . "NETTOTAL$"] = $Products["TOTAL"]["NETTOTAL"];
|
|
self::$rep["$" . $prefix . "TAXTOTAL$"] = $Products["TOTAL"]["TAXTOTAL"];
|
|
self::$rep["$" . $prefix . "FINALDISCOUNT$"] = $Products["TOTAL"]["FINALDISCOUNT"];
|
|
$this->replaceContent();
|
|
if ($is_related === false) {
|
|
|
|
$blockTypes = array('VATBLOCK', 'DEDUCTEDTAXESBLOCK', 'CHARGESBLOCK');
|
|
foreach ($blockTypes as $blockType) {
|
|
$vattable = "";
|
|
|
|
if (PDFMaker_Utils_Helper::count((array)$Products["TOTAL"][$blockType]) > 0) {
|
|
$vattable = '<table class="' . strtolower($blockType) . '_style" border="1" style="border-collapse:collapse;" cellpadding="3">';
|
|
$vattable .= '<tr>
|
|
';
|
|
if ($blockType == 'CHARGESBLOCK') {
|
|
$vattable .= '<td></td><td nowrap align="right">' . vtranslate("LBL_CHARGESBLOCK_SUM", "PDFMaker") . '</td>';
|
|
} else {
|
|
$vattable .= '<td nowrap align="center">' . vtranslate("Name") . '</td>
|
|
<td nowrap align="center">' . vtranslate("LBL_VATBLOCK_VAT_PERCENT", "PDFMaker") . '</td>
|
|
<td nowrap align="center">' . vtranslate("LBL_VATBLOCK_SUM", "PDFMaker") . ' (' . $currencytype["currency_symbol"] . ')</td>
|
|
<td nowrap align="center">' . vtranslate("LBL_VATBLOCK_VAT_VALUE", "PDFMaker") . ' (' . $currencytype["currency_symbol"] . ')</td>';
|
|
}
|
|
$vattable .= '</tr>';
|
|
foreach ($Products["TOTAL"][$blockType] as $keyW => $valueW) {
|
|
if ($valueW["netto"] != 0 || ($blockType == 'CHARGESBLOCK' && !empty($valueW['value']))) {
|
|
$vattable .= '<tr>';
|
|
if ($blockType == 'CHARGESBLOCK') {
|
|
$vattable .= '<td nowrap align="right" width="75%">' . $valueW['label'] . '</td>
|
|
<td nowrap align="right" width="25%">' . $this->formatNumberToPDF($valueW['value']) . '</td>';
|
|
} else {
|
|
$vattable .= '<td nowrap align="left" width="20%">' . $valueW['label'] . '</td>
|
|
<td nowrap align="right" width="25%">' . $this->formatNumberToPDF($valueW['value']) . ' %</td>
|
|
<td nowrap align="right" width="30%">' . $this->formatCurrencyToPDF($valueW['netto']) . '</td>
|
|
<td nowrap align="right" width="25%">' . $this->formatCurrencyToPDF($valueW['vat']) . '</td>';
|
|
}
|
|
$vattable .= '</tr>';
|
|
}
|
|
}
|
|
$vattable .= "</table>";
|
|
}
|
|
self::$rep["$" . $blockType . "$"] = $vattable;
|
|
|
|
$PDFMaker_Fields_Model = new PDFMaker_Fields_Model();
|
|
$MoreFields = $PDFMaker_Fields_Model->getMoreFields($module);
|
|
|
|
foreach ($MoreFields as $f_name => $f_lang) {
|
|
self::$rep["%" . $f_name . "%"] = $f_lang;
|
|
}
|
|
}
|
|
|
|
|
|
$this->replaceContent();
|
|
$VProductParts = array();
|
|
|
|
foreach (['VAT', 'CHARGES'] as $blockType) {
|
|
if (strpos(self::$content, '#' . $blockType . 'BLOCK_START#') !== false && strpos(self::$content, '#' . $blockType . 'BLOCK_END#') !== false) {
|
|
self::$content = $this->convertBlock(self::$content, $blockType);
|
|
$VExplodedPdf = [];
|
|
$VExploded = explode('#' . $blockType . 'BLOCK_START#', self::$content);
|
|
$VExplodedPdf[] = $VExploded[0];
|
|
for ($iterator = 1; $iterator < PDFMaker_Utils_Helper::count($VExploded); $iterator++) {
|
|
$VSubExploded = explode('#' . $blockType . 'BLOCK_END#', $VExploded[$iterator]);
|
|
foreach ($VSubExploded as $Vpart) {
|
|
$VExplodedPdf[] = $Vpart;
|
|
}
|
|
$Vhighestpartid = $iterator * 2 - 1;
|
|
$VProductParts[$Vhighestpartid] = $VExplodedPdf[$Vhighestpartid];
|
|
$VExplodedPdf[$Vhighestpartid] = '';
|
|
}
|
|
|
|
if (PDFMaker_Utils_Helper::count($Products['TOTAL'][$blockType . 'BLOCK']) > 0) {
|
|
foreach ($Products['TOTAL'][$blockType . 'BLOCK'] as $keyW => $valueW) {
|
|
foreach ($VProductParts as $productpartid => $productparttext) {
|
|
if ($valueW['netto'] != 0 || ($blockType == 'CHARGES' && !empty($valueW['value']))) {
|
|
foreach ($valueW as $vColl => $vVal) {
|
|
if (is_numeric($vVal)) {
|
|
if('value' === $vColl) {
|
|
$vVal = $this->formatNumberToPDF($vVal);
|
|
} else {
|
|
$vVal = $this->formatCurrencyToPDF($vVal);
|
|
}
|
|
}
|
|
|
|
$productparttext = str_replace('$' . $blockType . 'BLOCK_' . strtoupper($vColl) . '$', $vVal, $productparttext);
|
|
}
|
|
|
|
$VExplodedPdf[$productpartid] .= $productparttext;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
self::$content = implode('', $VExplodedPdf);
|
|
}
|
|
}
|
|
}
|
|
return $Products;
|
|
}
|
|
|
|
private function fillInventoryData($module, $focus)
|
|
{
|
|
if (!isset(self::$is_inventory_module[$module])) {
|
|
self::$is_inventory_module[$module] = $this->isInventoryModule($module);
|
|
}
|
|
if (self::$is_inventory_module[$module] || (isset($focus->column_fields["currency_id"]) && isset($focus->column_fields["conversion_rate"]) && isset($focus->column_fields["hdnGrandTotal"]))) {
|
|
self::$inventory_table_array[$module] = $focus->table_name;
|
|
self::$inventory_id_array[$module] = $focus->table_index;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
* @var string $module
|
|
* @var object $focus
|
|
*/
|
|
private function getInventoryCurrencyInfoCustom($module, $focus)
|
|
{
|
|
$record_id = '';
|
|
$inventory_table = self::$inventory_table_array[$module];
|
|
$inventory_id = self::$inventory_id_array[$module];
|
|
|
|
if (!empty($focus->id)) {
|
|
$record_id = $focus->id;
|
|
}
|
|
|
|
return $this->getInventoryCurrencyInfoCustomArray($inventory_table, $inventory_id, $record_id);
|
|
}
|
|
|
|
/**
|
|
* @param array $finalDetails
|
|
* @return int|float
|
|
*/
|
|
public function getTotalWithVat($finalDetails)
|
|
{
|
|
if ('individual' === $finalDetails['taxtype']) {
|
|
return $finalDetails['preTaxTotal'];
|
|
}
|
|
|
|
return $finalDetails['preTaxTotal'] + $finalDetails['tax_totalamount'];
|
|
}
|
|
|
|
public function retrieveProductsCurrencyFields(&$products, $finalDetails)
|
|
{
|
|
$currencyFieldsList = array(
|
|
'NETTOTAL' => 'hdnSubTotal',
|
|
'TAXTOTAL' => 'tax_totalamount',
|
|
'SHTAXTOTAL' => 'shtax_totalamount',
|
|
'TOTALAFTERDISCOUNT' => 'preTaxTotal',
|
|
'FINALDISCOUNT' => 'discountTotal_final',
|
|
'SHTAXAMOUNT' => 'shipping_handling_charge',
|
|
'DEDUCTEDTAXESTOTAL' => 'deductTaxesTotalAmount',
|
|
);
|
|
|
|
foreach ($currencyFieldsList as $variableName => $fieldName) {
|
|
$products['TOTAL'][$variableName] = $this->formatCurrencyToPDF($finalDetails[$fieldName]);
|
|
}
|
|
}
|
|
|
|
protected function isAllowedNewLineToBr($value)
|
|
{
|
|
return strpos($value, '<br />') === false &&
|
|
strpos($value, '<br/>') === false &&
|
|
strpos($value, '<br>') === false &&
|
|
strpos($value, '<li>') === false &&
|
|
strpos($value, '<br />') === false &&
|
|
strpos($value, '<br/>') === false &&
|
|
strpos($value, '<br>') === false &&
|
|
strpos($value, '<li>') === false;
|
|
}
|
|
|
|
protected function getTaxPercentageFromFinalDetails($finalDetails)
|
|
{
|
|
$percentage = 0;
|
|
|
|
foreach ((array)$finalDetails['taxes'] as $finalDetailTax) {
|
|
if (!empty((float)$finalDetailTax['percentage'])) {
|
|
$percentage += (float)$finalDetailTax['percentage'];
|
|
}
|
|
}
|
|
|
|
return $percentage;
|
|
}
|
|
|
|
/**
|
|
* @param string $module
|
|
* @param object $focus
|
|
* @return array
|
|
* @throws Exception
|
|
*/
|
|
private function getInventoryProducts($module, $focus)
|
|
{
|
|
$vatBlock = $finalDetails = $mpdfSubtotalAble = array();
|
|
$taxType = 'group';
|
|
$usageUnit = '';
|
|
$totalVatSum = $totalAfterDiscountSubTotal = $totalSubTotal = $totalSumSubTotal = 0;
|
|
|
|
if (!empty($focus->id)) {
|
|
$recordModel = Inventory_Record_Model::getInstanceById($focus->id);
|
|
|
|
if (!method_exists($recordModel, 'getProducts')) {
|
|
return array();
|
|
}
|
|
|
|
$relatedProducts = $recordModel->getProducts();
|
|
$finalDetails = $relatedProducts[1]['final_details'];
|
|
$taxType = $finalDetails['taxtype'];
|
|
|
|
$this->retrieveProductsCurrencyFields($Details, $finalDetails);
|
|
|
|
$totalWithVat = $this->getTotalWithVat($finalDetails);
|
|
$Details['TOTAL']['TOTALWITHVAT'] = $this->formatCurrencyToPDF($totalWithVat);
|
|
$Details['TOTAL']['TAXTYPE'] = $taxType;
|
|
|
|
$currencyType = $this->getInventoryCurrencyInfoCustom($module, $focus);
|
|
|
|
foreach ($relatedProducts as $i => $PData) {
|
|
$Details['P'][$i] = array(
|
|
'TAXTYPE' => $taxType,
|
|
);
|
|
|
|
$sequence = $i;
|
|
$productTitle = $productName = $PData['productName' . $sequence];
|
|
$entityType = $PData['entityType' . $sequence];
|
|
$productId = $psId = $PData['hdnProductId' . $sequence];
|
|
$productFocus = CRMEntity::getInstance('Products');
|
|
|
|
if ('Products' === $entityType && !empty($psId)) {
|
|
$productFocus->id = $psId;
|
|
$this->retrieve_entity_infoCustom($productFocus, $psId, $entityType);
|
|
}
|
|
|
|
$productInfo = $this->replaceFieldsToContent('Products', $productFocus, false, $currencyType);
|
|
$Details['P'][$i] = array_merge($productInfo, $Details['P'][$i]);
|
|
unset($productFocus);
|
|
|
|
$serviceFocus = CRMEntity::getInstance('Services');
|
|
|
|
if ('Services' === $entityType && !empty($psId)) {
|
|
$serviceFocus->id = $psId;
|
|
$this->retrieve_entity_infoCustom($serviceFocus, $psId, $entityType);
|
|
}
|
|
|
|
$serviceInfo = $this->replaceFieldsToContent('Services', $serviceFocus, false, $currencyType);
|
|
$Details['P'][$i] = array_merge($serviceInfo, $Details['P'][$i]);
|
|
unset($serviceFocus);
|
|
|
|
$Details['P'][$i]['PRODUCTS_CRMID'] = $Details['P'][$i]['SERVICES_CRMID'] = $qtyPerUnit = $module = '';
|
|
|
|
if ('Products' === $entityType) {
|
|
$Details['P'][$i]['PRODUCTS_CRMID'] = $psId;
|
|
$qtyPerUnit = $Details['P'][$i]['PRODUCTS_QTY_PER_UNIT'];
|
|
$usageUnit = $Details['P'][$i]['PRODUCTS_USAGEUNIT'];
|
|
} elseif ('Services' === $entityType) {
|
|
$Details['P'][$i]['SERVICES_CRMID'] = $psId;
|
|
$qtyPerUnit = $Details['P'][$i]['SERVICES_QTY_PER_UNIT'];
|
|
$usageUnit = $Details['P'][$i]['SERVICES_SERVICE_USAGEUNIT'];
|
|
}
|
|
|
|
$psDescription = $Details['P'][$i][strtoupper($entityType) . '_DESCRIPTION'];
|
|
$Details['P'][$i]['RECORD_ID'] = $Details['P'][$i]['PS_CRMID'] = $psId;
|
|
$Details['P'][$i]['PS_NO'] = $PData['hdnProductcode' . $sequence];
|
|
|
|
if (PDFMaker_Utils_Helper::count((array)$PData['subprod_qty_list' . $sequence]) > 0) {
|
|
$productName .= $this->getSubProductsForProductName($PData['subprod_qty_list' . $sequence]);
|
|
}
|
|
|
|
$comment = $PData['comment' . $sequence];
|
|
|
|
if (!empty($comment)) {
|
|
if ($this->isAllowedNewLineToBr($comment)) {
|
|
$comment = str_replace("\\n", "<br>", nl2br($comment));
|
|
}
|
|
|
|
$comment = html_entity_decode($comment, ENT_QUOTES, self::$def_charset);
|
|
$productName .= '<br /><small>' . $comment . '</small>';
|
|
}
|
|
|
|
$Details['P'][$i]['PRODUCTNAME'] = $productName;
|
|
|
|
if (!$this->isRecordExists($psId) && empty($productTitle)) {
|
|
$productTitle = $this->translateString('LBL_ITEM_DELETED_FROM_SYSTEM', 'PDFMaker');
|
|
}
|
|
|
|
$Details['P'][$i]['PRODUCTTITLE'] = $productTitle;
|
|
|
|
$inventoryProductRelDescription = $psDescription;
|
|
|
|
if ($this->isAllowedNewLineToBr($psDescription)) {
|
|
$psDescription = str_replace("\\n", '<br>', nl2br($psDescription));
|
|
}
|
|
|
|
$Details['P'][$i]['PRODUCTDESCRIPTION'] = html_entity_decode($psDescription, ENT_QUOTES,
|
|
self::$def_charset);
|
|
$Details['P'][$i]['PRODUCTEDITDESCRIPTION'] = $comment;
|
|
|
|
if (false === strpos($inventoryProductRelDescription, '<br />') &&
|
|
false === strpos($inventoryProductRelDescription, '<br/>') &&
|
|
false === strpos($inventoryProductRelDescription, '<br>')
|
|
) {
|
|
$inventoryProductRelDescription = str_replace("\\n", "<br>",
|
|
nl2br($inventoryProductRelDescription)
|
|
);
|
|
}
|
|
|
|
$Details['P'][$i]['CRMNOWPRODUCTDESCRIPTION'] = html_entity_decode($inventoryProductRelDescription,
|
|
ENT_QUOTES, self::$def_charset);
|
|
$Details['P'][$i]['PRODUCTLISTPRICE'] = $this->formatCurrencyToPDF($PData['listPrice' . $sequence]);
|
|
$Details['P'][$i]['PRODUCTTOTAL'] = $this->formatCurrencyToPDF($PData['productTotal' . $sequence]);
|
|
$Details['P'][$i]['PRODUCTQUANTITY'] = $this->formatNumberToPDF($PData['qty' . $sequence]);
|
|
$Details['P'][$i]['PRODUCTQINSTOCK'] = $this->formatNumberToPDF($PData['qtyInStock' . $sequence]);
|
|
$Details['P'][$i]['PRODUCTPRICE'] = $this->formatCurrencyToPDF($PData['unitPrice' . $sequence]);
|
|
$Details['P'][$i]['PRODUCTPOSITION'] = $sequence;
|
|
$Details['P'][$i]['PRODUCTQTYPERUNIT'] = $this->formatNumberToPDF($qtyPerUnit);
|
|
$Details['P'][$i]['PRODUCTUSAGEUNIT'] = $usageUnit;
|
|
$Details['P'][$i]['PRODUCTDISCOUNT'] = $this->formatCurrencyToPDF($PData['discountTotal' . $sequence]);
|
|
$Details['P'][$i]['PRODUCTDISCOUNTPERCENT'] = $this->formatNumberToPDF($PData['discount_percent' . $sequence]);
|
|
$totalAfterDiscount = $PData['totalAfterDiscount' . $sequence];
|
|
$Details['P'][$i]['PRODUCTSTOTALAFTERDISCOUNTSUM'] = $totalAfterDiscount;
|
|
$Details['P'][$i]['PRODUCTSTOTALAFTERDISCOUNT'] = $this->formatCurrencyToPDF($totalAfterDiscount);
|
|
|
|
$netPrice = (float)$PData['netPrice' . $sequence];
|
|
|
|
if ('individual' !== $taxType) {
|
|
$netPriceTax = $this->getTaxPercentageFromFinalDetails($finalDetails);
|
|
$netPrice += $netPrice / 100 * $netPriceTax;
|
|
}
|
|
|
|
$Details['P'][$i]['PRODUCTTOTALSUM'] = $this->formatCurrencyToPDF($netPrice);
|
|
$Details['P'][$i]['PRODUCT_LISTPRICEWITHTAX'] = $this->formatCurrencyToPDF($netPrice / $PData['qty' . $sequence]);
|
|
|
|
$totalAfterDiscountSubTotal += $totalAfterDiscount;
|
|
$totalSubTotal += $PData['productTotal' . $sequence];
|
|
$totalSumSubTotal += $netPrice;
|
|
|
|
$Details['P'][$i]['PRODUCTSTOTALAFTERDISCOUNT_SUBTOTAL'] = $this->formatCurrencyToPDF($totalAfterDiscountSubTotal);
|
|
$Details['P'][$i]['PRODUCTTOTAL_SUBTOTAL'] = $this->formatCurrencyToPDF($totalSubTotal);
|
|
$Details['P'][$i]['PRODUCTTOTALSUM_SUBTOTAL'] = $this->formatCurrencyToPDF($totalSumSubTotal);
|
|
|
|
$mpdfSubtotalAble[$i]['$TOTALAFTERDISCOUNT_SUBTOTAL$'] = $Details['P'][$i]['PRODUCTSTOTALAFTERDISCOUNT_SUBTOTAL'];
|
|
$mpdfSubtotalAble[$i]['$TOTAL_SUBTOTAL$'] = $Details['P'][$i]['PRODUCTTOTAL_SUBTOTAL'];
|
|
$mpdfSubtotalAble[$i]['$TOTALSUM_SUBTOTAL$'] = $Details['P'][$i]['PRODUCTTOTALSUM_SUBTOTAL'];
|
|
|
|
$Details['P'][$i]['PRODUCTSEQUENCE'] = $sequence;
|
|
$Details['P'][$i]['PRODUCTS_IMAGENAME'] = $this->getProductImage($focus->id, self::$site_url, $productId, $sequence);
|
|
$Details['P'][$i]['PRODUCT_IMAGE'] = $Details['P'][$i]['PRODUCTS_IMAGENAME'];
|
|
|
|
$taxTotal = $taxAvgValue = 0;
|
|
|
|
if ('individual' === $taxType) {
|
|
$lineItemId = $this->getItemIdBySequence($i, $focus->id);
|
|
$taxDetails = getTaxDetailsForProduct($productId, 'all');
|
|
$taxValues = array();
|
|
$vatPercent = array();
|
|
$totalTaxValues = array();
|
|
|
|
foreach ($taxDetails as $taxDetail) {
|
|
$taxName = $taxDetail['taxname'];
|
|
$taxLabel = $taxDetail['taxlabel'];
|
|
$taxValue = getInventoryProductTaxValue($focus->id, $productId, $taxName, $lineItemId);
|
|
$individualTaxAmount = $totalAfterDiscount * $taxValue / 100;
|
|
$taxTotal = $taxTotal + $individualTaxAmount;
|
|
|
|
if ($taxName != '') {
|
|
$taxKey = $taxName . '-' . $taxValue;
|
|
|
|
$vatSum = round($individualTaxAmount, self::$decimals);
|
|
$totalVatSum += $vatSum;
|
|
|
|
$vatBlock[$taxKey]['label'] = $taxLabel;
|
|
$vatBlock[$taxKey]['netto'] += $totalAfterDiscount;
|
|
$vatBlock[$taxKey]['vat'] += $vatSum;
|
|
$vatBlock[$taxKey]['value'] = $taxValue;
|
|
array_push($taxValues, $taxValue);
|
|
array_push($totalTaxValues, $taxValue);
|
|
array_push($vatPercent, $this->formatNumberToPDF($taxValue));
|
|
}
|
|
}
|
|
|
|
if (PDFMaker_Utils_Helper::count($taxValues) > 0) {
|
|
$taxAvgValue = array_sum($taxValues);
|
|
}
|
|
|
|
$vatPercentString = implode(', ', array_filter($vatPercent));
|
|
|
|
$Details['P'][$i]['VATPERCENT_INDIVIDUAL'] = $vatPercentString ?: '0';
|
|
$Details['TOTAL']['VATPERCENT_INDIVIDUAL'][] = $vatPercentString;
|
|
} else {
|
|
$taxAvgValue = $this->getTaxPercentageFromFinalDetails($finalDetails);
|
|
$taxTotal = !empty($taxAvgValue) ? $totalAfterDiscount * $taxAvgValue / 100 : 0;
|
|
}
|
|
|
|
$Details['P'][$i]['PRODUCTVATPERCENT'] = $this->formatNumberToPDF($taxAvgValue);
|
|
$Details['P'][$i]['PRODUCTVATSUM'] = $this->formatNumberToPDF($taxTotal);
|
|
|
|
$result1 = self::$db->pquery('SELECT * FROM vtiger_inventoryproductrel WHERE id=? AND sequence_no=?',
|
|
array(self::$focus->id, $sequence)
|
|
);
|
|
$row1 = self::$db->fetchByAssoc($result1, 0);
|
|
$result2 = self::$db->pquery('SELECT fieldname, fieldlabel, columnname, uitype, typeofdata FROM vtiger_field WHERE tablename = ? AND tabid = ?',
|
|
array('vtiger_inventoryproductrel', getTabid(self::$module))
|
|
);
|
|
|
|
while ($row2 = self::$db->fetchByAssoc($result2)) {
|
|
if (!isset($Details['P'][$i]['PRODUCT_' . strtoupper($row2['fieldname'])])) {
|
|
$UITypes = array();
|
|
$value = $row1[$row2['columnname']];
|
|
|
|
if (!empty($value)) {
|
|
$uiTypeName = $this->getUITypeName($row2['uitype'], $row2['typeofdata']);
|
|
|
|
if (!empty($uiTypeName)) {
|
|
$UITypes[$uiTypeName][] = $row2['fieldname'];
|
|
}
|
|
|
|
$value = $this->getFieldValue($focus, $module, $row2['fieldname'], $value, $UITypes);
|
|
}
|
|
|
|
$Details['P'][$i]['PRODUCT_' . strtoupper($row2['fieldname'])] = $value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$Details['TOTAL']['TOTALWITHOUTVAT'] = $this->formatCurrencyToPDF($totalAfterDiscountSubTotal);
|
|
|
|
|
|
$totalVatPercentage = 0;
|
|
|
|
if ('individual' === $taxType) {
|
|
$Details['TOTAL']['TAXTOTAL'] = $this->formatCurrencyToPDF($totalVatSum);
|
|
} else {
|
|
$vatBlock = $this->getGroupVatBlock($finalDetails);
|
|
$totalVatPercentage = $this->getTotalVatPercentage($finalDetails);
|
|
}
|
|
|
|
$Details['TOTAL']['TAXTOTALPERCENT'] = $this->formatNumberToPDF($totalVatPercentage);
|
|
$Details['TOTAL']['VATBLOCK'] = $vatBlock;
|
|
$Details['TOTAL']['CHARGESBLOCK'] = $this->getChargesBlock($finalDetails);
|
|
|
|
$finalDiscountAmount = !empty($focus->column_fields['hdnDiscountAmount']) ? $focus->column_fields['hdnDiscountAmount'] : '';
|
|
$finalDiscountPercent = !empty($focus->column_fields['hdnDiscountPercent']) ? $focus->column_fields['hdnDiscountPercent'] : '';
|
|
|
|
$Details['TOTAL']['FINALDISCOUNTPERCENT'] = $this->formatNumberToPDF($finalDiscountPercent);
|
|
$Details['TOTAL']['FINALDISCOUNTAMOUNT'] = $this->formatNumberToPDF($finalDiscountAmount);
|
|
$Details['TOTAL']['DEDUCTEDTAXESBLOCK'] = $this->getDeductedTaxesBlock($finalDetails);
|
|
|
|
return $Details;
|
|
}
|
|
|
|
public function getSubProductsForProductName($values)
|
|
{
|
|
$productName = '';
|
|
|
|
foreach ($values as $id => $data) {
|
|
$name = $data['name'];
|
|
|
|
if (0 < $data['qty']) {
|
|
$name .= ' (' . $data['qty'] . ')';
|
|
}
|
|
|
|
$productName .= '<br/><span style="color:#C0C0C0;font-style: italic;"><span class="SubProductsForProductName">' . $name . '</span></span>';
|
|
}
|
|
|
|
return $productName;
|
|
}
|
|
|
|
/**
|
|
* @param array $finalDetails
|
|
* @return array
|
|
*/
|
|
public function getGroupVatBlock($finalDetails)
|
|
{
|
|
if (empty($finalDetails['taxes'])) {
|
|
return array();
|
|
}
|
|
|
|
$vatBlock = array();
|
|
|
|
foreach ($finalDetails['taxes'] as $tax) {
|
|
$taxName = $tax['taxname'];
|
|
$vatBlock[$taxName]['netto'] = $finalDetails['totalAfterDiscount'];
|
|
$vatBlock[$taxName]['label'] = $tax['taxlabel'];
|
|
$vatBlock[$taxName]['value'] = $tax['percentage'];
|
|
|
|
if (isset($vatBlock[$taxName]['vat'])) {
|
|
$vatBlock[$taxName]['vat'] += $tax['amount'];
|
|
} else {
|
|
$vatBlock[$taxName]['vat'] = $tax['amount'];
|
|
}
|
|
}
|
|
|
|
return $vatBlock;
|
|
}
|
|
|
|
/**
|
|
* @param array $finalDetails
|
|
* @return int|float
|
|
*/
|
|
public function getTotalVatPercentage($finalDetails)
|
|
{
|
|
if (empty($finalDetails['taxes'])) {
|
|
return 0;
|
|
}
|
|
|
|
$percentage = 0;
|
|
|
|
foreach ($finalDetails['taxes'] as $tax) {
|
|
$percentage += $tax['percentage'];
|
|
}
|
|
|
|
return $percentage;
|
|
}
|
|
|
|
/**
|
|
* @param array $finalDetails
|
|
* @return array
|
|
*/
|
|
public function getChargesBlock($finalDetails)
|
|
{
|
|
if (empty($finalDetails['chargesAndItsTaxes'])) {
|
|
return array();
|
|
}
|
|
|
|
$chargesBlock = array();
|
|
$allCharges = getAllCharges();
|
|
$chargesAndItsTaxes = $finalDetails['chargesAndItsTaxes'];
|
|
|
|
foreach ($chargesAndItsTaxes as $chargeId => $chargeData) {
|
|
$name = $allCharges[$chargeId]['name'];
|
|
$chargesBlock[] = array(
|
|
'label' => $name,
|
|
'value' => $chargeData['value']
|
|
);
|
|
}
|
|
|
|
return $chargesBlock;
|
|
}
|
|
|
|
public function getDeductedTaxesBlock($finalDetails)
|
|
{
|
|
if (empty($finalDetails['deductTaxes'])) {
|
|
return array();
|
|
}
|
|
|
|
$deductTaxesBlock = array();
|
|
|
|
foreach ($finalDetails['deductTaxes'] as $deductTax) {
|
|
$taxName = $deductTax['taxname'];
|
|
|
|
$deductTaxesBlock[$taxName]['label'] = $deductTax['taxlabel'];
|
|
$deductTaxesBlock[$taxName]['netto'] = $finalDetails['totalAfterDiscount'];
|
|
$deductTaxesBlock[$taxName]['vat'] = $deductTax['amount'];
|
|
$deductTaxesBlock[$taxName]['value'] = $deductTax['percentage'];
|
|
}
|
|
|
|
return $deductTaxesBlock;
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
* @var object $focus
|
|
* @var int $record
|
|
* @var string $module
|
|
*/
|
|
private function retrieve_entity_infoCustom(&$focus, $record, $module)
|
|
{
|
|
$result = array();
|
|
|
|
foreach ($focus->tab_name_index as $table_name => $index) {
|
|
$result[$table_name] = self::$db->pquery(sprintf('SELECT * FROM %s WHERE %s=?', $table_name, $index),
|
|
array($record)
|
|
);
|
|
}
|
|
|
|
$tabId = getTabid($module);
|
|
$result1 = self::$db->pquery('SELECT fieldname, fieldid, fieldlabel, columnname, tablename, uitype, typeofdata, presence FROM vtiger_field WHERE tabid=?', array($tabId));
|
|
|
|
if (self::$db->num_rows($result1)) {
|
|
while ($row1 = self::$db->fetch_array($result1)) {
|
|
$columnName = $row1['columnname'];
|
|
$tableName = $row1['tablename'];
|
|
$fieldName = $row1['fieldname'];
|
|
$fieldValue = '';
|
|
|
|
if (isset($result[$tableName])) {
|
|
$fieldValue = self::$db->query_result($result[$tableName], 0, $columnName);
|
|
}
|
|
|
|
$focus->column_fields[$fieldName] = $fieldValue;
|
|
}
|
|
}
|
|
|
|
$focus->column_fields['record_id'] = $record;
|
|
$focus->column_fields['record_module'] = $module;
|
|
}
|
|
|
|
/**
|
|
* @param int $sequence
|
|
* @param int $record
|
|
* @return int
|
|
* @throws Exception
|
|
*/
|
|
public function getItemIdBySequence($sequence, $record)
|
|
{
|
|
$result = self::$db->pquery('SELECT lineitem_id FROM vtiger_inventoryproductrel WHERE id=? AND sequence_no=?', [$record, $sequence]);
|
|
|
|
return (int)self::$db->query_result($result, 0, 'lineitem_id');
|
|
}
|
|
|
|
private function getFieldValue($efocus, $emodule, $fieldname, $value, $UITypes, $inventory_currency = false)
|
|
{
|
|
return $this->getFieldValueUtils($efocus, $emodule, $fieldname, $value, $UITypes, $inventory_currency, self::$ignored_picklist_values, self::$def_charset, self::$decimals, self::$decimal_point, self::$thousands_separator, self::$language, self::$focus->id);
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
public function getRelatedBlockSecondaryModule($relatedBlockId)
|
|
{
|
|
$result = self::$db->pquery('SELECT secmodule FROM vtiger_pdfmaker_relblocks WHERE relblockid = ?', array($relatedBlockId));
|
|
|
|
return self::$db->query_result($result, 0, 'secmodule');
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
private function convertRelatedBlocks()
|
|
{
|
|
include_once("modules/PDFMaker/resources/RelBlockRun.php");
|
|
|
|
if (false !== strpos(self::$content, "#RELBLOCK")) {
|
|
preg_match_all("|#RELBLOCK([0-9]+)_START#|U", self::$content, $relatedBlocks, PREG_PATTERN_ORDER);
|
|
|
|
if (PDFMaker_Utils_Helper::count($relatedBlocks[1]) > 0) {
|
|
$convertRelBlock = array();
|
|
$productParts = array();
|
|
|
|
foreach ($relatedBlocks[1] as $relatedBlockId) {
|
|
if (!in_array($relatedBlockId, $convertRelBlock)) {
|
|
$secondaryModule = $this->getRelatedBlockSecondaryModule($relatedBlockId);
|
|
|
|
if (self::strContain(self::$content, '#RELBLOCK' . $relatedBlockId . '_START#') && self::strContain(self::$content, '#RELBLOCK' . $relatedBlockId . '_END#')) {
|
|
$this->convertRelatedBlock($relatedBlockId);
|
|
|
|
$relatedBlockRun = new RelBlockRun(self::$focus->id, $relatedBlockId, self::$module, $secondaryModule);
|
|
$relatedBlockRun->SetPDFLanguage(self::$language);
|
|
$relatedBlockData = $relatedBlockRun->GenerateReport();
|
|
|
|
$explodedPdf = array();
|
|
$exploded = explode('#RELBLOCK' . $relatedBlockId . '_START#', self::$content);
|
|
$explodedPdf[] = $exploded[0];
|
|
|
|
for ($iterator = 1; $iterator < PDFMaker_Utils_Helper::count($exploded); $iterator++) {
|
|
$subExploded = explode('#RELBLOCK' . $relatedBlockId . '_END#', $exploded[$iterator]);
|
|
|
|
foreach ($subExploded as $subExplodedPart) {
|
|
$explodedPdf[] = $subExplodedPart;
|
|
}
|
|
|
|
$highestPartId = $iterator * 2 - 1;
|
|
$productParts[$highestPartId] = $explodedPdf[$highestPartId];
|
|
$explodedPdf[$highestPartId] = '';
|
|
}
|
|
|
|
if (!in_array($secondaryModule, self::$relBlockModules)) {
|
|
self::$relBlockModules[] = $secondaryModule;
|
|
}
|
|
|
|
if (PDFMaker_Utils_Helper::count($relatedBlockData) > 0) {
|
|
$rowId = 0;
|
|
|
|
foreach ($relatedBlockData as $relatedBlockDetail) {
|
|
$rowId++;
|
|
$relatedBlockDetail['ROW_ID'] = $rowId;
|
|
|
|
foreach ($productParts as $productPartId => $productPartText) {
|
|
$show_line = false;
|
|
|
|
foreach ($relatedBlockDetail as $coll => $value) {
|
|
if (trim($value) != "-" && $coll != "listprice") {
|
|
$show_line = true;
|
|
}
|
|
|
|
$productPartText = str_ireplace("$" . $coll . "$", $value, $productPartText);
|
|
}
|
|
|
|
if ($show_line) {
|
|
$explodedPdf[$productPartId] .= $productPartText;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
self::$content = implode('', $explodedPdf);
|
|
}
|
|
|
|
$convertRelBlock[] = $relatedBlockId;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private function convertRelatedBlock($relBlockId)
|
|
{
|
|
PDFMaker_PDFMaker_Model::getSimpleHtmlDomFile();
|
|
$html = str_get_html(self::$content);
|
|
|
|
if (is_array($html->find("td"))) {
|
|
foreach ($html->find("td") as $td) {
|
|
if (trim($td->plaintext) == "#RELBLOCK" . $relBlockId . "_START#") {
|
|
$td->parent->outertext = "#RELBLOCK" . $relBlockId . "_START#";
|
|
}
|
|
if (trim($td->plaintext) == "#RELBLOCK" . $relBlockId . "_END#") {
|
|
$td->parent->outertext = "#RELBLOCK" . $relBlockId . "_END#";
|
|
}
|
|
}
|
|
|
|
self::$content = $html->save();
|
|
}
|
|
}
|
|
|
|
private function convertInventoryModules()
|
|
{
|
|
|
|
$result = self::$db->pquery("select * from vtiger_inventoryproductrel where id=?", array(self::$focus->id));
|
|
$num_rows = self::$db->num_rows($result);
|
|
|
|
if ($num_rows > 0) {
|
|
$products = $this->replaceInventoryDetailsBlock(self::$module, self::$focus);
|
|
$blockTypes = array('', 'PRODUCTS_', 'SERVICES_', 'UNIQUE_');
|
|
|
|
foreach ($blockTypes as $blockType) {
|
|
if (strpos(self::$content, "#PRODUCTBLOC_" . $blockType . "START#") !== false && strpos(self::$content, "#PRODUCTBLOC_" . $blockType . "END#") !== false) {
|
|
$tableTag = $this->convertProductBlock($blockType);
|
|
$breakLinesData = $this->getInventoryBreaklines(self::$focus->id);
|
|
$breakLineType = $this->getBreakLineType($breakLinesData, $tableTag);
|
|
|
|
$this->replaceProducts($products, $blockType, $breakLinesData['products'], $breakLineType);
|
|
}
|
|
}
|
|
|
|
self::$rep['$VATPERCENT_INDIVIDUAL$'] = implode(', ', array_filter((array)$products['TOTAL']['VATPERCENT_INDIVIDUAL']));
|
|
$this->replaceContent();
|
|
}
|
|
}
|
|
|
|
public function getBreakLineType($breakLinesData, $tableTag)
|
|
{
|
|
$breakLines = $breakLinesData['products'];
|
|
$breakLineType = '';
|
|
|
|
if (PDFMaker_Utils_Helper::count($breakLines) > 0) {
|
|
if ($tableTag !== false) {
|
|
if (1 === $breakLinesData['show_subtotal']) {
|
|
$breakLineType = $tableTag['subtotal'];
|
|
} else {
|
|
$breakLineType = $tableTag['footer'];
|
|
}
|
|
|
|
$breakLineType .= '</table>' . PDFMaker_PageBreak_Model::PAGE_BREAK_TAG . $tableTag['tag'];
|
|
|
|
if (1 === $breakLinesData['show_header']) {
|
|
$breakLineType .= $tableTag['header'];
|
|
}
|
|
} else {
|
|
$breakLineType = PDFMaker_PageBreak_Model::PAGE_BREAK_TAG;
|
|
}
|
|
}
|
|
|
|
return $breakLineType;
|
|
}
|
|
|
|
/**
|
|
* @param array $products
|
|
* @param string $blockType
|
|
* @param array $breakLines
|
|
* @param string $breakLineType
|
|
* @return void
|
|
*/
|
|
public function replaceProducts($products, $blockType = '', $breakLines = array(), $breakLineType = '')
|
|
{
|
|
$exploded = explode('#PRODUCTBLOC_' . $blockType . 'START#', self::$content);
|
|
$explodedContent = [
|
|
$exploded[0]
|
|
];
|
|
|
|
for ($iterator = 1; $iterator < PDFMaker_Utils_Helper::count($exploded); $iterator++) {
|
|
$subExploded = explode("#PRODUCTBLOC_" . $blockType . "END#", $exploded[$iterator]);
|
|
|
|
foreach ($subExploded as $subExplode) {
|
|
$explodedContent[] = $subExplode;
|
|
}
|
|
|
|
$highestPartId = $iterator * 2 - 1;
|
|
$productParts[$highestPartId] = $explodedContent[$highestPartId];
|
|
$explodedContent[$highestPartId] = '';
|
|
}
|
|
|
|
if (isset($products['P'])) {
|
|
$userProductIds = [];
|
|
|
|
foreach ($products['P'] as $productDetails) {
|
|
$productId = $productDetails['RECORD_ID'];
|
|
|
|
if (($blockType == 'PRODUCTS_' && empty($productDetails['PRODUCTS_CRMID'])) || ($blockType == 'SERVICES_' && empty($productDetails['SERVICES_CRMID']))) {
|
|
continue;
|
|
}
|
|
|
|
foreach ($productParts as $productPartId => $productPartText) {
|
|
if ('UNIQUE_' == $blockType && in_array($productId, $userProductIds)) {
|
|
$productPartText = '';
|
|
}
|
|
|
|
$userProductIds[] = $productId;
|
|
|
|
if (!empty($breakLineType) && isset($breakLines[$productDetails['RECORD_ID'] . '_' . $productDetails['PRODUCTSEQUENCE']])) {
|
|
$productPartText .= $breakLineType;
|
|
}
|
|
|
|
foreach ($productDetails as $column => $value) {
|
|
$value = is_null($value) ? '' : $value;
|
|
$productPartText = str_replace('$' . strtoupper($column) . '$', $value, $productPartText);
|
|
}
|
|
|
|
$explodedContent[$productPartId] .= $productPartText;
|
|
}
|
|
}
|
|
}
|
|
|
|
self::$content = implode('', $explodedContent);
|
|
}
|
|
|
|
private function convertProductBlock($block_type = '')
|
|
{
|
|
PDFMaker_PDFMaker_Model::getSimpleHtmlDomFile();
|
|
$html = str_get_html(self::$content);
|
|
$tableDOM = false;
|
|
|
|
if (is_array($html->find("td"))) {
|
|
foreach ($html->find("td") as $td) {
|
|
if (trim($td->plaintext) == "#PRODUCTBLOC_" . $block_type . "START#") {
|
|
$td->parent->outertext = "#PRODUCTBLOC_" . $block_type . "START#";
|
|
$oParent = $td->parent;
|
|
while ($oParent->tag != "table") {
|
|
$oParent = $oParent->parent;
|
|
}
|
|
list($tag) = explode(">", $oParent->outertext, 2);
|
|
$header = $oParent->first_child();
|
|
if ($header->tag != "tr") {
|
|
$header = $header->children(0);
|
|
}
|
|
$header_style = '';
|
|
|
|
if (is_object($td->parent->prev_sibling()->children[0])) {
|
|
$header_style = $td->parent->prev_sibling()->children[0]->getAttribute("style");
|
|
}
|
|
$footer_tag = "<tr>";
|
|
if (isset($header_style)) {
|
|
$StyleHeader = explode(";", $header_style);
|
|
if (isset($StyleHeader)) {
|
|
foreach ($StyleHeader as $style_header_tag) {
|
|
if (strpos($style_header_tag, "border-top") == true) {
|
|
$footer_tag .= "<td colspan='" . $td->getAttribute("colspan") . "' style='" . $style_header_tag . "'> </td>";
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
$footer_tag .= "<td colspan='" . $td->getAttribute("colspan") . "' style='border-top:1px solid #000000;'> </td>";
|
|
}
|
|
$footer_tag .= "</tr>";
|
|
$var = $td->parent->next_sibling()->last_child()->plaintext;
|
|
|
|
$subtotal_tr = "";
|
|
if (strpos($var, "TOTAL") !== false) {
|
|
if (is_object($td)) {
|
|
$style_subtotal = $td->getAttribute("style");
|
|
}
|
|
$style_subtotal_tag = $style_subtotal_endtag = "";
|
|
if (isset($td->innertext)) {
|
|
list($style_subtotal_tag, $style_subtotal_endtag) = explode("#PRODUCTBLOC_" . $block_type . "START#", $td->innertext);
|
|
}
|
|
if (isset($style_subtotal)) {
|
|
$StyleSubtotal = explode(";", $style_subtotal);
|
|
if (isset($StyleSubtotal)) {
|
|
foreach ($StyleSubtotal as $style_tag) {
|
|
if (strpos($style_tag, "border-top") == true) {
|
|
$tag .= " style='" . $style_tag . "'";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
$style_subtotal = "";
|
|
}
|
|
|
|
$subtotal_tr = "<tr>";
|
|
$preg_cond = '/\$([A-Z]*)\$/';
|
|
preg_match($preg_cond, $var, $var_array);
|
|
$var_text = $var_array[1];
|
|
|
|
$var_split = preg_split($preg_cond, $var);
|
|
|
|
$subtotal_tr .= "<td colspan='" . ($td->getAttribute("colspan") - 1) . "' style='" . $style_subtotal . ";border-right:none'>" . $style_subtotal_tag . "%G_Subtotal%" . $style_subtotal_endtag . "</td>";
|
|
$subtotal_tr .= "<td align='right' nowrap='nowrap' style='" . $style_subtotal . "'>" . $style_subtotal_tag . $var_split[0] . "$" . $var_text . "_SUBTOTAL$" . $var_split[1] . $style_subtotal_endtag . "</td>";
|
|
$subtotal_tr .= "</tr>";
|
|
}
|
|
$tag .= ">";
|
|
$tableDOM["tag"] = $tag;
|
|
$tableDOM["header"] = $header->outertext;
|
|
$tableDOM["footer"] = $footer_tag;
|
|
$tableDOM["subtotal"] = $subtotal_tr;
|
|
}
|
|
if (trim($td->plaintext) == "#PRODUCTBLOC_" . $block_type . "END#") {
|
|
$td->parent->outertext = "#PRODUCTBLOC_" . $block_type . "END#";
|
|
}
|
|
}
|
|
self::$content = $html->save();
|
|
}
|
|
|
|
return $tableDOM;
|
|
}
|
|
|
|
private function handleRowbreak()
|
|
{
|
|
$html = str_get_html(self::$content);
|
|
$toSkip = 0;
|
|
|
|
if (is_array($html->find("rowbreak"))) {
|
|
foreach ($html->find("rowbreak") as $pb) {
|
|
if ($pb->outertext == self::$rowbreak) {
|
|
$tmpPb = $pb;
|
|
while ($tmpPb != null && $tmpPb->tag != "td") {
|
|
$tmpPb = $tmpPb->parent();
|
|
}
|
|
if ($tmpPb->tag == "td") {
|
|
if ($toSkip > 0) {
|
|
$toSkip--;
|
|
continue;
|
|
}
|
|
$prev_sibling = $tmpPb->prev_sibling();
|
|
$prev_sibling_styles = array();
|
|
while ($prev_sibling != null) {
|
|
$prev_sibling_styles[] = $this->getDOMElementAtts($prev_sibling);
|
|
$prev_sibling = $prev_sibling->prev_sibling();
|
|
}
|
|
$next_sibling = $tmpPb->next_sibling();
|
|
$next_sibling_styles = array();
|
|
while ($next_sibling != null) {
|
|
$next_sibling_styles[] = $this->getDOMElementAtts($next_sibling);
|
|
$next_sibling = $next_sibling->next_sibling();
|
|
}
|
|
|
|
$partsArr = explode(self::$rowbreak, $tmpPb->innertext);
|
|
for ($i = 0; $i < (count($partsArr) - 1); $i++) {
|
|
$tmpPb->innertext = $partsArr[$i];
|
|
|
|
$addition = '<tr>';
|
|
for ($j = 0; $j < count($prev_sibling_styles); $j++) {
|
|
$addition .= '<td ' . $prev_sibling_styles[$j] . '> </td>';
|
|
}
|
|
$addition .= '<td style="' . $tmpPb->getAttribute("style") . '">' . $partsArr[$i + 1] . '</td>';
|
|
for ($j = 0; $j < count($next_sibling_styles); $j++) {
|
|
$addition .= '<td ' . $next_sibling_styles[$j] . '> </td>';
|
|
}
|
|
$addition .= '</tr>';
|
|
|
|
$tmpPb->parent()->outertext = $tmpPb->parent()->outertext . $addition;
|
|
}
|
|
$toSkip = count($partsArr) - 2;
|
|
}
|
|
}
|
|
}
|
|
self::$content = $html->save();
|
|
}
|
|
}
|
|
|
|
private function replaceUserCompanyFields()
|
|
{
|
|
$current_user = Users_Record_Model::getCurrentUserModel();
|
|
|
|
if (getTabId('ITS4YouMultiCompany') && PDFMaker_Module_Model::isModuleActive('ITS4YouMultiCompany')) {
|
|
$CompanyDetailsRecord_Model = ITS4YouMultiCompany_Record_Model::getCompanyInstance(self::$focus->column_fields["assigned_user_id"]);
|
|
$CompanyDetails_Model = $CompanyDetailsRecord_Model->getModule();
|
|
$CompanyDetails_Data = $CompanyDetailsRecord_Model->getData();
|
|
$ismulticompany = true;
|
|
} else {
|
|
$CompanyDetails_Model = Settings_Vtiger_CompanyDetails_Model::getInstance();
|
|
$CompanyDetails_Data = $CompanyDetails_Model->getData();
|
|
$ismulticompany = false;
|
|
}
|
|
$CompanyDetails_Fields = $CompanyDetails_Model->getFields();
|
|
|
|
foreach ($CompanyDetails_Fields as $field_name => $field_data) {
|
|
$value = "";
|
|
|
|
if ($field_name == "organizationname" || $field_name == "companyname") {
|
|
$coll = "name";
|
|
} elseif ($field_name == "street") {
|
|
$coll = "address";
|
|
} elseif ($field_name == "code") {
|
|
$coll = "zip";
|
|
} elseif ($field_name == "logoname") {
|
|
continue;
|
|
} else {
|
|
$coll = $field_name;
|
|
}
|
|
if ('logo' === $coll && !empty($CompanyDetails_Data['logoname'])) {
|
|
$value = '<img src="' . self::$site_url . '/' . LOGO_PATH . $CompanyDetails_Data["logoname"] . '">';
|
|
} elseif (($coll == "logo" || $coll == "stamp") && $ismulticompany && !empty($CompanyDetails_Data[$coll])) {
|
|
$value = $this->getAttachmentImage($CompanyDetails_Data[$coll], self::$site_url);
|
|
} elseif (isset($CompanyDetails_Data[$field_name])) {
|
|
$value = $CompanyDetails_Data[$field_name];
|
|
}
|
|
self::$rep["$" . "COMPANY_" . strtoupper($coll) . "$"] = $value;
|
|
|
|
if ($ismulticompany) {
|
|
$label = vtranslate($field_data->get("label"), "ITS4YouMultiCompany");
|
|
} else {
|
|
$label = vtranslate($field_name, "Settings:Vtiger");
|
|
}
|
|
|
|
self::$rep["%" . "COMPANY_" . strtoupper($coll) . "%"] = $label;
|
|
}
|
|
$result = self::$db->pquery("SELECT tandc FROM vtiger_inventory_tandc WHERE type = ?", array('Inventory'));
|
|
$tandc = self::$db->query_result($result, 0, "tandc");
|
|
$tandc = is_null($tandc) ? '' : $tandc;
|
|
|
|
if (strpos($tandc, '<br />') === false && strpos($tandc, '<br/>') === false && strpos($tandc, '<br>') === false) {
|
|
self::$rep["$" . "TERMS_AND_CONDITIONS$"] = nl2br($tandc);
|
|
}
|
|
if (self::$focus->column_fields["assigned_user_id"] != "") {
|
|
$user_res = self::$db->pquery("SELECT * FROM vtiger_users WHERE id = ?", array(self::$focus->column_fields["assigned_user_id"]));
|
|
$user_row = self::$db->fetchByAssoc($user_res);
|
|
|
|
$this->replaceUserData($user_row["id"], $user_row, "USER");
|
|
} else {
|
|
$this->replaceUserData($current_user->id, $current_user, "USER");
|
|
}
|
|
$this->replaceUserData($current_user->id, $current_user, "L_USER");
|
|
|
|
$focus_user = CRMEntity::getInstance("Users");
|
|
$focus_user->id = self::$focus->column_fields["assigned_user_id"];
|
|
$this->retrieve_entity_infoCustom($focus_user, $focus_user->id, "Users");
|
|
$this->replaceFieldsToContent("Users", $focus_user, false);
|
|
$curr_user_focus = CRMEntity::getInstance("Users");
|
|
$curr_user_focus->id = $current_user->id;
|
|
$this->retrieve_entity_infoCustom($curr_user_focus, $curr_user_focus->id, "Users");
|
|
$this->replaceFieldsToContent("Users", $curr_user_focus, true);
|
|
self::$rep["$" . "USERS_CRMID$"] = $focus_user->id;
|
|
self::$rep["$" . "R_USERS_CRMID$"] = $curr_user_focus->id;
|
|
|
|
$modifiedby_user_res = self::$db->pquery("SELECT vtiger_users.* FROM vtiger_users INNER JOIN vtiger_crmentity ON vtiger_crmentity.modifiedby = vtiger_users.id WHERE vtiger_crmentity.crmid = ?", array(self::$focus->id));
|
|
$modifiedby_user_row = self::$db->fetchByAssoc($modifiedby_user_res);
|
|
$this->replaceUserData($modifiedby_user_row["id"], $modifiedby_user_row, "M_USER");
|
|
$modifiedby_user_focus = CRMEntity::getInstance("Users");
|
|
$modifiedby_user_focus->id = $modifiedby_user_row["id"];
|
|
$this->retrieve_entity_infoCustom($modifiedby_user_focus, $modifiedby_user_focus->id, "Users");
|
|
$this->replaceFieldsToContent("Users", $modifiedby_user_focus, true, false, 'M_');
|
|
|
|
$smcreatorid_user_res = self::$db->pquery("SELECT vtiger_users.* FROM vtiger_users INNER JOIN vtiger_crmentity ON vtiger_crmentity.smcreatorid = vtiger_users.id WHERE vtiger_crmentity.crmid = ?", array(self::$focus->id));
|
|
$smcreatorid_user_row = self::$db->fetchByAssoc($smcreatorid_user_res);
|
|
$this->replaceUserData($smcreatorid_user_row["id"], $smcreatorid_user_row, "C_USER");
|
|
$smcreatorid_user_focus = CRMEntity::getInstance("Users");
|
|
$smcreatorid_user_focus->id = $smcreatorid_user_row["id"];
|
|
$this->retrieve_entity_infoCustom($smcreatorid_user_focus, $smcreatorid_user_focus->id, "Users");
|
|
$this->replaceFieldsToContent("Users", $smcreatorid_user_focus, true, false, 'C_');
|
|
|
|
$this->replaceContent();
|
|
}
|
|
|
|
private function replaceUserData($id, $data, $type)
|
|
{
|
|
$Fields = array(
|
|
"FIRSTNAME" => "first_name",
|
|
"LASTNAME" => "last_name",
|
|
"EMAIL" => "email1",
|
|
"TITLE" => "title",
|
|
"FAX" => "phone_fax",
|
|
"DEPARTMENT" => "department",
|
|
"OTHER_EMAIL" => "email2",
|
|
"PHONE" => "phone_work",
|
|
"YAHOOID" => "yahoo_id",
|
|
"MOBILE" => "phone_mobile",
|
|
"HOME_PHONE" => "phone_home",
|
|
"OTHER_PHONE" => "phone_other",
|
|
"SIGHNATURE" => "signature",
|
|
"NOTES" => "description",
|
|
"ADDRESS" => "address_street",
|
|
"COUNTRY" => "address_country",
|
|
"CITY" => "address_city",
|
|
"ZIP" => "address_postalcode",
|
|
"STATE" => "address_state"
|
|
);
|
|
|
|
foreach ($Fields as $n => $v) {
|
|
self::$rep["$" . $type . "_" . $n . "$"] = $this->getUserValue($v, $data);
|
|
}
|
|
|
|
$currency_id = $this->getUserValue("currency_id", $data);
|
|
$currency_info = $this->getInventoryCurrencyInfoCustomArray('', '', $currency_id);
|
|
|
|
if ($type == "L_USER") {
|
|
$type = "R_USER";
|
|
}
|
|
|
|
self::$rep["$" . $type . "S_IMAGENAME$"] = $this->getUserImage($id);
|
|
self::$rep["$" . $type . "S_CRMID$"] = $id;
|
|
self::$rep["$" . $type . "S_CURRENCY_NAME$"] = $currency_info["currency_name"];
|
|
self::$rep["$" . $type . "S_CURRENCY_CODE$"] = $currency_info["currency_code"];
|
|
self::$rep["$" . $type . "S_CURRENCY_SYMBOL$"] = $currency_info["currency_symbol"];
|
|
$this->replaceContent();
|
|
}
|
|
|
|
private function replaceLabels()
|
|
{
|
|
$PDFMaker = new PDFMaker_PDFMaker_Model();
|
|
$app_lang_array = Vtiger_Language_Handler::getModuleStringsFromFile(self::$language);
|
|
$mod_lang_array = Vtiger_Language_Handler::getModuleStringsFromFile(self::$language, self::$module);
|
|
$app_lang = $app_lang_array["languageStrings"];
|
|
$mod_lang = $mod_lang_array["languageStrings"];
|
|
|
|
list($custom_lang, $languages) = $PDFMaker->GetCustomLabels();
|
|
$currLangId = "";
|
|
foreach ($languages as $langId => $langVal) {
|
|
if ($langVal["prefix"] == self::$language) {
|
|
$currLangId = $langId;
|
|
break;
|
|
}
|
|
}
|
|
self::$rep["%G_Qty%"] = $app_lang["Quantity"];
|
|
self::$rep["%G_Subtotal%"] = $app_lang["Sub Total"];
|
|
self::$rep["%M_LBL_VENDOR_NAME_TITLE%"] = $app_lang["Vendor Name"];
|
|
$this->replaceContent();
|
|
if (strpos(self::$content, "%G_") !== false) {
|
|
foreach ($app_lang as $key => $value) {
|
|
self::$rep["%G_" . $key . "%"] = $value;
|
|
}
|
|
$this->replaceContent();
|
|
}
|
|
if (strpos(self::$content, "%M_") !== false) {
|
|
foreach ($mod_lang as $key => $value) {
|
|
self::$rep["%M_" . $key . "%"] = $value;
|
|
}
|
|
$this->replaceContent();
|
|
foreach ($app_lang as $key => $value) {
|
|
self::$rep["%M_" . $key . "%"] = $value;
|
|
}
|
|
if (self::$module == "SalesOrder") {
|
|
self::$rep["%G_SO Number%"] = $mod_lang["SalesOrder No"];
|
|
}
|
|
if (self::$module == "Invoice") {
|
|
self::$rep["%G_Invoice No%"] = $mod_lang["Invoice No"];
|
|
}
|
|
self::$rep["%M_Grand Total%"] = vtranslate('Grand Total', self::$module);
|
|
$this->replaceContent();
|
|
}
|
|
if (strpos(self::$content, "%C_") !== false) {
|
|
foreach ($custom_lang as $key => $value) {
|
|
self::$rep["%" . $value->GetKey() . "%"] = $value->GetLangValue($currLangId);
|
|
}
|
|
$this->replaceContent();
|
|
}
|
|
if (count(self::$relBlockModules) > 0) {
|
|
$services_lang = return_specified_module_language(self::$language, "Services");
|
|
$contacts_lang = return_specified_module_language(self::$language, "Contacts");
|
|
foreach (self::$relBlockModules as $relBlockModule) {
|
|
if ($relBlockModule != "") {
|
|
$relMod_lang = return_specified_module_language(self::$language, $relBlockModule);
|
|
$r_rbm_upper = "%R_" . strtoupper($relBlockModule);
|
|
self::$rep[$r_rbm_upper . "_Service Name%"] = $services_lang["Service Name"];
|
|
self::$rep[$r_rbm_upper . "_Secondary Email%"] = $contacts_lang["Secondary Email"];
|
|
|
|
$LD = $this->getRelBlockLabels();
|
|
foreach ($LD as $lkey => $llabel) {
|
|
self::$rep[$r_rbm_upper . "_" . $lkey . "%"] = $app_lang[$llabel];
|
|
}
|
|
$rl_res = self::$db->pquery("SELECT vtiger_field.fieldlabel FROM vtiger_field INNER JOIN vtiger_tab ON vtiger_tab.tabid = vtiger_field.tabid WHERE vtiger_tab.name = ?", array($relBlockModule));
|
|
while ($rl_row = self::$db->fetchByAssoc($rl_res)) {
|
|
$key = $rl_row["fieldlabel"];
|
|
if ($relMod_lang[$key]) {
|
|
$value = $relMod_lang[$key];
|
|
} elseif ($app_lang[$key]) {
|
|
$value = $app_lang[$key];
|
|
} else {
|
|
$value = $key;
|
|
}
|
|
self::$rep[$r_rbm_upper . "_" . htmlentities($key, ENT_QUOTES, self::$def_charset) . "%"] = $value;
|
|
}
|
|
|
|
$this->setCustomReplace($relBlockModule);
|
|
$this->replaceContent();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $value
|
|
* @param string $module
|
|
* @return string
|
|
*/
|
|
public function translateString($value, $module)
|
|
{
|
|
return Vtiger_Language_Handler::getTranslatedString($value, $module, self::$language);
|
|
}
|
|
|
|
/**
|
|
* @param string $module
|
|
*/
|
|
public function setCustomReplace($module)
|
|
{
|
|
$relStartReplace = "%R_" . strtoupper($module);
|
|
|
|
if ('Products' === $module) {
|
|
self::$rep[$relStartReplace . '_LBL_LIST_PRICE%'] = $this->translateString('LBL_LIST_PRICE', $module);
|
|
}
|
|
|
|
if ('Calendar' == $module) {
|
|
self::$rep[$relStartReplace . '_Start Date & Time%'] = $this->translateString('Start Date & Time', $module);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $type
|
|
*/
|
|
private function convertHideTR($type = '')
|
|
{
|
|
$regex = '/<tr\b[^<]*>[^<]*(?:<(?!tr\b)[^<]*)*#' . $type . 'HIDETR#[^<]*(?:<(?!\/tr>)[^<]*)*<\/tr>/';
|
|
|
|
self::$content = preg_replace($regex, '', self::$content);
|
|
}
|
|
|
|
private function replaceCustomFunctions()
|
|
{
|
|
global $PDFContent;
|
|
|
|
$PDFContent = $this;
|
|
|
|
self::$content = $this->stringToCustomFunction(self::$content);
|
|
self::$filename = $this->stringToCustomFunction(self::$filename);
|
|
}
|
|
|
|
/**
|
|
* @param string $value
|
|
* @return string
|
|
*/
|
|
private function stringToCustomFunction($value)
|
|
{
|
|
if (false !== strpos($value, '[CUSTOMFUNCTION|')) {
|
|
foreach (glob('modules/PDFMaker/resources/functions/*.php') as $file) {
|
|
include_once $file;
|
|
}
|
|
|
|
$AllowedFunctions = (new PDFMaker_AllowedFunctions_Helper())->getAllowedFunctions();
|
|
$startFunctions = explode('[CUSTOMFUNCTION|', $value);
|
|
$content = $startFunctions[0];
|
|
|
|
foreach ($startFunctions as $function) {
|
|
$endFunction = explode("|CUSTOMFUNCTION]", $function);
|
|
$html = $endFunction[0];
|
|
|
|
if (!empty($html)) {
|
|
$Params = $this->getCustomfunctionParams($html);
|
|
$func = $Params[0];
|
|
unset($Params[0]);
|
|
|
|
if (in_array($func, $AllowedFunctions)) {
|
|
$content .= call_user_func_array($func, $Params);
|
|
}
|
|
}
|
|
|
|
$content .= $endFunction[1];
|
|
}
|
|
|
|
$value = $content;
|
|
}
|
|
|
|
return $value;
|
|
}
|
|
|
|
public function getFilename()
|
|
{
|
|
return $this->getInputContent("filename");
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getTemplateName()
|
|
{
|
|
return self::$templatename;
|
|
}
|
|
|
|
/**
|
|
* @param string $type
|
|
* @return string
|
|
*/
|
|
public function getInputContent($type)
|
|
{
|
|
if ('filename' === $type) {
|
|
$val = self::$filename;
|
|
} elseif ('pdfpassword' === $type) {
|
|
$val = self::$pdf_password;
|
|
} elseif ('watermark_text' === $type) {
|
|
$val = self::$watermark_text;
|
|
}
|
|
|
|
if (empty($val)) {
|
|
return '';
|
|
}
|
|
|
|
$Rep = array();
|
|
$Rep['$#TEMPLATE_NAME#$'] = self::$templatename;
|
|
$Rep['$#DD-MM-YYYY#$'] = date('d-m-Y');
|
|
$Rep['$#MM-DD-YYYY#$'] = date('m-d-Y');
|
|
$Rep['$#YYYY-MM-DD#$'] = date('Y-m-d');
|
|
$Rep["\r\n"] = $Rep["\n\r"] = $Rep["\n"] = $Rep["\r"] = '';
|
|
$val = str_replace(array_keys($Rep), $Rep, $val);
|
|
$val = html_entity_decode($val, ENT_QUOTES, self::$def_charset);
|
|
|
|
if ('filename' === $type) {
|
|
return str_replace(' ', '_', substr(strip_tags($val), 0, 255));
|
|
} elseif ('pdfpassword' === $type) {
|
|
return trim(strip_tags($val));
|
|
} else {
|
|
return $val;
|
|
}
|
|
}
|
|
|
|
public function getPDFPassword()
|
|
{
|
|
return $this->getInputContent("pdfpassword");
|
|
}
|
|
|
|
public function getWatermarkText()
|
|
{
|
|
return $this->getInputContent("watermark_text");
|
|
}
|
|
|
|
public function getSettings()
|
|
{
|
|
$Settings = $this->getSettingsForId(self::$templateid);
|
|
|
|
$Settings["watermark"] = array(
|
|
"type" => $Settings["watermark_type"],
|
|
"text" => $Settings["watermark_text"],
|
|
"img_id" => $Settings["watermark_img_id"],
|
|
"alpha" => ($Settings["watermark_alpha"] != "" ? $Settings["watermark_alpha"] : "0.1")
|
|
);
|
|
|
|
return $Settings;
|
|
}
|
|
|
|
private function getInventoryTaxTypeCustom($module, $focus)
|
|
{
|
|
if (!empty($focus->id)) {
|
|
$res = self::$db->pquery("SELECT taxtype FROM " . self::$inventory_table_array[$module] . " WHERE " . self::$inventory_id_array[$module] . "=?", array($focus->id));
|
|
return self::$db->query_result($res, 0, 'taxtype');
|
|
}
|
|
return "";
|
|
}
|
|
|
|
private function itsmd($val)
|
|
{
|
|
return md5($val);
|
|
}
|
|
|
|
public function isAllowedExportEdit()
|
|
{
|
|
return '1' !== self::$disable_export_edit;
|
|
}
|
|
|
|
public function retrievePageBreak($data = array())
|
|
{
|
|
if (!empty($data)) {
|
|
self::$pagebreak = '<pagebreak sheet-size="' . $this->getPageBreakFormat($data) . '" orientation="' . $data["orientation"] . '" margin-left="' . ($data["margin_left"] * 10) . 'mm" margin-right="' . ($data["margin_right"] * 10) . 'mm" margin-top="0mm" margin-bottom="0mm" margin-header="' . ($data["margin_top"] * 10) . 'mm" margin-footer="' . ($data["margin_bottom"] * 10) . 'mm" />';
|
|
} else {
|
|
self::$pagebreak = '<br clear=all style="mso-special-character:line-break;page-break-before:always">';
|
|
}
|
|
}
|
|
|
|
public function getPageBreak($data = array())
|
|
{
|
|
if (!self::$pagebreak) {
|
|
$this->retrievePageBreak($data);
|
|
}
|
|
|
|
return self::$pagebreak;
|
|
}
|
|
|
|
public function getDocumentFileName()
|
|
{
|
|
return self::$filename;
|
|
}
|
|
|
|
public static $numberFormat = [];
|
|
|
|
public static function getNumberFormat($templateId)
|
|
{
|
|
if (empty(self::$numberFormat[$templateId])) {
|
|
$adb = PearDatabase::getInstance();
|
|
$result = $adb->pquery('SELECT decimals, decimal_point, thousands_separator, currency, currency_point, currency_thousands FROM vtiger_pdfmaker_settings WHERE templateid=?',
|
|
[$templateId]
|
|
);
|
|
|
|
self::$numberFormat[$templateId] = $adb->fetch_array($result);
|
|
}
|
|
|
|
return self::$numberFormat[$templateId];
|
|
}
|
|
|
|
/**
|
|
* @param Vtiger_Field_Model $field
|
|
* @param Vtiger_Record_Model $record
|
|
* @throws Exception
|
|
*/
|
|
public function updateCalendarField($field, $record)
|
|
{
|
|
switch ($field->get('name')) {
|
|
case 'date_start':
|
|
$field->set('fieldvalue', $record->get('date_start') . ' ' . $record->get('time_start'));
|
|
break;
|
|
case 'due_date':
|
|
$field->set('fieldvalue', $record->get('due_date') . ' ' . $record->get('time_end'));
|
|
break;
|
|
}
|
|
}
|
|
} |