YetiForceCompany/YetiForceCRM

View on GitHub
modules/Vtiger/models/ExportToXml.php

Summary

Maintainability
D
1 day
Test Coverage
F
0%
<?php

/**
 * Export to XML model file.
 *
 * @package Model
 *
 * @copyright YetiForce S.A.
 * @license   YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
 * @author    Radosław Skrzypczak <r.skrzypczak@yetiforce.com>
 * @author    Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com>
 */

/**
 * Export to XML model class.
 */
class Vtiger_ExportToXml_Model extends \App\Export\Records
{
    protected $attrList = ['crmfield', 'crmfieldtype', 'partvalue', 'constvalue', 'refmoule', 'spec', 'refkeyfld', 'delimiter', 'testcondition'];
    protected $product = false;
    protected $tplName = '';
    protected $tmpXmlPath = '';
    protected $inventoryFields;
    protected $fileExtension = 'xml';

    /**
     * Set template.
     *
     * @param string $tplName
     *
     * @return $this
     */
    public function setTemplate(string $tplName)
    {
        $this->tplName = $tplName;

        return $this;
    }

    /** {@inheritdoc} */
    public function exportData()
    {
        $fileName = str_replace(' ', '_', \App\Purifier::decodeHtml(\App\Language::translate($this->moduleName, $this->moduleName)));
        $entriesInventory = [];
        $addInventoryData = $this->fullData && $this->moduleInstance->isInventory();
        $count = 0;
        $dataReader = $this->getExportQuery()->createCommand()->query();
        while ($row = $dataReader->read()) {
            $this->tmpXmlPath = 'cache/import/' . uniqid() . '_.xml';
            $this->xmlList[] = $this->tmpXmlPath;
            if ($addInventoryData) {
                $entriesInventory = $this->getEntriesInventory($row) ?: [];
            }
            if ($this->tplName) {
                $this->createXmlFromTemplate($row, $entriesInventory);
            } else {
                $this->createXml($this->sanitizeValues($row), $entriesInventory);
            }
            ++$count;
        }
        if (1 < $count) {
            $this->outputZipFile($fileName);
        } else {
            $this->outputFile($fileName);
        }
    }

    /**
     * Function returns data from advanced block.
     *
     * @param array $recordData
     *
     * @return array
     */
    public function getEntriesInventory($recordData): array
    {
        $entries = [];
        $inventoryModel = Vtiger_Inventory_Model::getInstance($this->moduleName);
        $this->inventoryFields = $inventoryModel->getFields();
        $table = $inventoryModel->getDataTableName();
        $dataReader = (new \App\Db\Query())->from($table)->where(['crmid' => $recordData['id']])->orderBy(['seq' => SORT_ASC])->createCommand()->query();
        while ($inventoryRow = $dataReader->read()) {
            $entries[] = $inventoryRow;
        }
        $dataReader->close();

        return $entries;
    }

    /**
     * Sanitize inventory value.
     *
     * @param mixed  $value
     * @param string $columnName
     *
     * @return string
     */
    public function sanitizeInventoryValue($value, $columnName): string
    {
        if ($field = $this->inventoryFields[$columnName] ?? false) {
            if (\in_array($field->getType(), ['Name', 'Reference'])) {
                $value = trim($value);
                if (!empty($value)) {
                    $recordModule = \App\Record::getType($value);
                    $displayValue = \App\Record::getLabel($value);
                    if (!empty($recordModule) && !empty($displayValue)) {
                        $value = $recordModule . '::::' . $displayValue;
                    } else {
                        $value = '';
                    }
                } else {
                    $value = '';
                }
            } elseif ('Currency' === $field->getType()) {
                $value = $field->getDisplayValue($value);
            }
        } elseif (\in_array($columnName, ['taxparam', 'discountparam', 'currencyparam'])) {
            if ('currencyparam' === $columnName) {
                $field = $this->inventoryFields['currency'];
                $valueData = $field->getCurrencyParam([], $value);
                $valueNewData = [];
                foreach ($valueData as $currencyId => &$data) {
                    $currencyName = \App\Fields\Currency::getById($currencyId)['currency_name'];
                    $data['value'] = $currencyName;
                    $valueNewData[$currencyName] = $data;
                }
                $value = \App\Json::encode($valueNewData);
            }
        }
        return html_entity_decode($value);
    }

    public function outputFile($fileName)
    {
        header("content-disposition: attachment;filename=$fileName.xml");
        header('content-type: text/csv;charset=UTF-8');
        header('expires: Mon, 31 Dec 2000 00:00:00 GMT');
        header('last-modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
        header('cache-control: post-check=0, pre-check=0', false);

        readfile($this->tmpXmlPath);
        unlink($this->tmpXmlPath);
    }

    protected function outputZipFile($fileName)
    {
        $zipName = 'cache/import/' . uniqid() . '.zip';

        $zip = new ZipArchive();
        $zip->open($zipName, ZipArchive::CREATE);
        $countXmlList = \count($this->xmlList);
        for ($i = 0; $i < $countXmlList; ++$i) {
            $xmlFile = basename($this->xmlList[$i]);
            $xmlFile = explode('_', $xmlFile);
            array_shift($xmlFile);
            $xmlFile = $fileName . $i . implode('_', $xmlFile);
            $zip->addFile($this->xmlList[$i], $xmlFile);
        }
        $zip->close();

        header("content-disposition: attachment;filename=$fileName.zip");
        header('content-type: application/zip');
        header('expires: Mon, 31 Dec 2000 00:00:00 GMT');
        header('last-modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
        header('cache-control: post-check=0, pre-check=0', false);
        readfile($zipName);
        unlink($zipName);
        array_map('unlink', $this->xmlList);
    }

    /**
     * Create XML file.
     *
     * @param array $entries
     * @param array $entriesInventory
     *
     * @return void
     */
    public function createXml($entries, $entriesInventory)
    {
        $exportBlockName = \App\Config::component('Export', 'BLOCK_NAME');
        $xml = new \XMLWriter();
        $xml->openMemory();
        $xml->setIndent(true);
        $xml->startDocument('1.0', 'UTF-8');
        $xml->startElement('MODULE_FIELDS');
        foreach ($this->fields as $fieldName => $fieldModel) {
            if ($fieldModel->get('source_field_name')) {
                continue;
            }
            $xml->startElement($fieldName);
            $header = \App\Language::translate(\App\Purifier::decodeHtml($fieldModel->get('label')), $this->moduleName);
            if ($exportBlockName) {
                $header = \App\Language::translate(\App\Purifier::decodeHtml($fieldModel->getBlockName()), $this->moduleName) . '::' . $header;
            }
            $xml->writeAttribute('type', $fieldModel->getFieldDataType());
            $xml->writeAttribute('label', $header);
            if ($this->isCData($fieldName)) {
                $xml->writeCData($entries[$fieldName]);
            } else {
                $xml->text($entries[$fieldName]);
            }
            $xml->endElement();
        }
        if ($entriesInventory) {
            $customColumns = [];
            $xml->startElement('INVENTORY_ITEMS');
            foreach ($entriesInventory as $inventory) {
                unset($inventory['id'], $inventory['crmid']);

                $xml->startElement('INVENTORY_ITEM');
                foreach ($inventory as $columnName => $value) {
                    $xml->startElement($columnName);
                    if ($fieldModel = ($this->inventoryFields[$columnName] ?? false)) {
                        $xml->writeAttribute('label', \App\Language::translate(html_entity_decode($fieldModel->get('label'), ENT_QUOTES), $this->moduleName));
                        if (!\in_array($columnName, $customColumns)) {
                            foreach ($fieldModel->getCustomColumn() as $key => $dataType) {
                                $customColumns[$key] = $columnName;
                            }
                        }
                    }
                    if ($this->isCData($columnName, $customColumns)) {
                        $xml->writeCData($this->sanitizeInventoryValue($value, $columnName));
                    } else {
                        $xml->text($this->sanitizeInventoryValue($value, $columnName));
                    }
                    $xml->endElement();
                }
                $xml->endElement();
            }
            $xml->endElement();
        }
        $xml->endElement();
        file_put_contents($this->tmpXmlPath, $xml->flush(true), FILE_APPEND);
    }

    public function isCData($name, $customColumns = [])
    {
        if ($customColumns) {
            return \array_key_exists($name, $customColumns);
        }
        if (($fieldModel = $this->moduleFieldInstances[$name] ?? false) && \in_array($fieldModel->getFieldDataType(), ['text', 'multiEmail'])) {
            return true;
        }
        return false;
    }

    public function createXmlFromTemplate($entries, $entriesInventory)
    {
    }
}