Add OnlyOfficeTemplates module
This commit is contained in:
172
modules/OnlyOfficeTemplates/resources/MergeService.php
Normal file
172
modules/OnlyOfficeTemplates/resources/MergeService.php
Normal file
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
/**
|
||||
* Merge DOCX template: load from S3, substitute {{field}} and {{ModuleName__field}}, output DOCX.
|
||||
*/
|
||||
|
||||
class OnlyOfficeTemplates_MergeService
|
||||
{
|
||||
protected $s3;
|
||||
protected $config;
|
||||
|
||||
public function __construct(OnlyOfficeTemplates_S3Helper $s3, array $config)
|
||||
{
|
||||
$this->s3 = $s3;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build placeholder map for a record: current module fields + related (Account, Contact, etc.).
|
||||
*
|
||||
* @param string $module
|
||||
* @param int $recordId
|
||||
* @return array [ 'fieldname' => value, 'Account__accountname' => value, ... ]
|
||||
*/
|
||||
public function buildPlaceholders($module, $recordId)
|
||||
{
|
||||
$adb = PearDatabase::getInstance();
|
||||
$focus = CRMEntity::getInstance($module);
|
||||
$focus->id = $recordId;
|
||||
$focus->retrieve_entity_info($recordId, $module);
|
||||
$fields = $focus->column_fields;
|
||||
|
||||
$map = [];
|
||||
foreach ($fields as $k => $v) {
|
||||
if ($v === null || $v === '') {
|
||||
$v = '';
|
||||
}
|
||||
$map[$k] = is_string($v) ? $v : (string)$v;
|
||||
}
|
||||
$map = array_merge($map, $this->getRelatedModuleFields($module, $recordId, $focus));
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get related entity fields (Account, Contact, etc.) for placeholder {{ModuleName__fieldname}}.
|
||||
*/
|
||||
protected function getRelatedModuleFields($module, $recordId, CRMEntity $focus)
|
||||
{
|
||||
$map = [];
|
||||
$relFields = $this->getRelationFieldNames($module);
|
||||
foreach ($relFields as $relModule => $fieldName) {
|
||||
$relId = isset($focus->column_fields[$fieldName]) ? $focus->column_fields[$fieldName] : null;
|
||||
if (empty($relId)) {
|
||||
continue;
|
||||
}
|
||||
$relFocus = CRMEntity::getInstance($relModule);
|
||||
$relFocus->retrieve_entity_info($relId, $relModule);
|
||||
foreach ($relFocus->column_fields as $k => $v) {
|
||||
if ($v === null || $v === '') {
|
||||
$v = '';
|
||||
}
|
||||
$map[$relModule . '__' . $k] = is_string($v) ? $v : (string)$v;
|
||||
}
|
||||
}
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common relation field names per module (account_id, contact_id, related_to, parent_id, etc.).
|
||||
*/
|
||||
/** @return array [ 'RelatedModule' => 'local_field_name', ... ] */
|
||||
protected function getRelationFieldNames($module)
|
||||
{
|
||||
$known = [
|
||||
'Project' => ['Accounts' => 'account_id', 'Contacts' => 'contact_id'],
|
||||
'Contacts' => ['Accounts' => 'account_id'],
|
||||
'Leads' => ['Accounts' => 'account_id'],
|
||||
'Potentials' => ['Accounts' => 'related_to', 'Contacts' => 'contact_id'],
|
||||
'Invoice' => ['Accounts' => 'account_id', 'Contacts' => 'contact_id'],
|
||||
'Quotes' => ['Accounts' => 'account_id', 'Contacts' => 'contact_id'],
|
||||
'SalesOrder' => ['Accounts' => 'account_id', 'Contacts' => 'contact_id'],
|
||||
'PurchaseOrder' => ['Vendors' => 'vendor_id', 'Contacts' => 'contact_id'],
|
||||
'HelpDesk' => ['Accounts' => 'parent_id', 'Contacts' => 'contact_id'],
|
||||
'Accounts' => [],
|
||||
];
|
||||
if (isset($known[$module])) {
|
||||
return $known[$module];
|
||||
}
|
||||
$out = [];
|
||||
if (in_array($module, ['Contacts', 'Leads', 'Potentials', 'Invoice', 'Quotes', 'SalesOrder'])) {
|
||||
$out['Accounts'] = 'account_id';
|
||||
if ($module !== 'Accounts') {
|
||||
$out['Contacts'] = 'contact_id';
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge template: download from S3, replace placeholders, save to temp file.
|
||||
*
|
||||
* @param string $s3Key template S3 key
|
||||
* @param array $placeholders [ 'field' => 'value', 'Account__name' => 'value' ]
|
||||
* @return string path to merged DOCX file
|
||||
*/
|
||||
public function mergeToFile($s3Key, array $placeholders)
|
||||
{
|
||||
$path = dirname(dirname(dirname(__DIR__)));
|
||||
if (!class_exists('PhpOffice\PhpWord\IOFactory')) {
|
||||
if (is_file($path . '/vendor/autoload.php')) {
|
||||
require_once $path . '/vendor/autoload.php';
|
||||
}
|
||||
}
|
||||
$tempDir = sys_get_temp_dir() . '/oot_' . uniqid();
|
||||
if (!is_dir($tempDir)) {
|
||||
mkdir($tempDir, 0755, true);
|
||||
}
|
||||
$templatePath = $tempDir . '/template.docx';
|
||||
$this->s3->downloadToFile($s3Key, $templatePath);
|
||||
|
||||
$phpWord = \PhpOffice\PhpWord\IOFactory::load($templatePath);
|
||||
$this->replaceInPhpWord($phpWord, $placeholders);
|
||||
$outPath = $tempDir . '/merged.docx';
|
||||
$writer = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007');
|
||||
$writer->save($outPath);
|
||||
@unlink($templatePath);
|
||||
return $outPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace {{placeholder}} in all text elements.
|
||||
*/
|
||||
protected function replaceInPhpWord(\PhpOffice\PhpWord\PhpWord $phpWord, array $placeholders)
|
||||
{
|
||||
foreach ($phpWord->getSections() as $section) {
|
||||
foreach ($section->getElements() as $element) {
|
||||
$this->replaceInElement($element, $placeholders);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function replaceInElement($element, array $placeholders)
|
||||
{
|
||||
if ($element instanceof \PhpOffice\PhpWord\Element\Text) {
|
||||
$text = $element->getText();
|
||||
$text = $this->replacePlaceholders($text, $placeholders);
|
||||
$element->setText($text);
|
||||
return;
|
||||
}
|
||||
if ($element instanceof \PhpOffice\PhpWord\Element\TextRun) {
|
||||
foreach ($element->getElements() as $el) {
|
||||
$this->replaceInElement($el, $placeholders);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ($element instanceof \PhpOffice\PhpWord\Element\TextBreak) {
|
||||
return;
|
||||
}
|
||||
if (method_exists($element, 'getElements')) {
|
||||
foreach ($element->getElements() as $el) {
|
||||
$this->replaceInElement($el, $placeholders);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function replacePlaceholders($text, array $placeholders)
|
||||
{
|
||||
foreach ($placeholders as $key => $value) {
|
||||
$text = str_replace('{{' . $key . '}}', $value, $text);
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user