Passed
Push — developer ( a71332...bcab7f )
by Radosław
16:27
created

Vtiger_ExportToSpreadsheet_Model::exportData()   B

Complexity

Conditions 7
Paths 20

Size

Total Lines 27
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 18
c 1
b 0
f 0
dl 0
loc 27
rs 8.8333
cc 7
nc 20
nop 0
1
<?php
2
3
/**
4
 * Export to spreadsheet model file.
5
 *
6
 * @package Model
7
 *
8
 * @copyright YetiForce S.A.
9
 * @license   YetiForce Public License 5.0 (licenses/LicenseEN.txt or yetiforce.com)
10
 * @author    Mariusz Krzaczkowski <[email protected]>
11
 * @author    Radosław Skrzypczak <[email protected]>
12
 */
13
/**
14
 * Export to spreadsheet model class.
15
 */
16
class Vtiger_ExportToSpreadsheet_Model extends \App\Export\ExportRecords
17
{
18
	protected $workBook;
19
	protected $workSheet;
20
	protected $headerStyles;
21
	protected $colNo = 1;
22
	protected $rowNo = 1;
23
	protected $invNo = 0;
24
25
	/**
26
	 * Constructor.
27
	 */
28
	public function __construct()
29
	{
30
		parent::__construct();
31
		$this->workBook = new \PhpOffice\PhpSpreadsheet\Spreadsheet();
32
		$this->workSheet = $this->workBook->setActiveSheetIndex(0);
33
		$this->headerStyles = [
34
			'fill' => ['type' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID, 'color' => ['argb' => 'E1E0F7']],
35
			'font' => ['bold' => true],
36
		];
37
	}
38
39
	/** {@inheritdoc} */
40
	public function getHeaders(): array
41
	{
42
		$headers = parent::getHeaders();
43
		foreach ($headers as $header) {
44
			$this->workSheet->setCellValueExplicitByColumnAndRow($this->colNo, $this->rowNo, $header, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
45
			++$this->colNo;
46
		}
47
		++$this->rowNo;
48
		return $headers;
49
	}
50
51
	/** {@inheritdoc} */
52
	public function output($headers, $entries)
0 ignored issues
show
Unused Code introduced by
The parameter $entries is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

52
	public function output($headers, /** @scrutinizer ignore-unused */ $entries)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
53
	{
54
		//having written out all the data lets have a go at getting the columns to auto-size
55
		$row = $col = 1;
56
		$length = \count($headers);
57
		for ($i = 1; $i <= $length; ++$i) {
58
			$cell = $this->workSheet->getCellByColumnAndRow($col, $row);
59
			$this->workSheet->getStyleByColumnAndRow($col, $row)->applyFromArray($this->headerStyles);
60
			$this->workSheet->getColumnDimension($cell->getColumn())->setAutoSize(true);
61
			++$col;
62
		}
63
		$tempFileName = tempnam(ROOT_DIRECTORY . DIRECTORY_SEPARATOR . \App\Config::main('tmp_dir'), 'xls');
64
		$workbookWriter = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($this->workBook, ucfirst($this->fileExtension));
65
		$workbookWriter->save($tempFileName);
66
		$fp = fopen($tempFileName, 'r');
67
		fpassthru($fp);
68
		fclose($fp);
69
		unlink($tempFileName);
70
	}
71
72
	/** {@inheritdoc} */
73
	public function exportData()
74
	{
75
		$headers = $this->getHeaders();
76
77
		$addInventoryData = $this->fullData && $this->moduleInstance->isInventory();
78
		if ($addInventoryData) {
79
			$inventoryModel = Vtiger_Inventory_Model::getInstance($this->moduleName);
80
			$inventoryFields = $inventoryModel->getFields();
81
			$inventoryTable = $inventoryModel->getDataTableName();
82
		}
83
		$dataReader = $this->getExportQuery()->createCommand()->query();
84
		while ($row = $dataReader->read()) {
85
			if ($addInventoryData) {
86
				$invRows = (new \App\Db\Query())->from($inventoryTable)->where(['crmid' => $row['id']])->orderBy('seq')->all();
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $inventoryTable does not seem to be defined for all execution paths leading up to this point.
Loading history...
87
				if ($invRows) {
88
					foreach ($invRows as $invRow) {
89
						$this->sanitizeValues($row);
90
						$this->sanitizeInventoryValues($invRow, $inventoryFields);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $inventoryFields does not seem to be defined for all execution paths leading up to this point.
Loading history...
91
					}
92
				}
93
			} else {
94
				$this->sanitizeValues($row);
95
			}
96
		}
97
		$dataReader->close();
98
99
		$this->output($headers, []);
100
	}
101
102
	/** {@inheritdoc} */
103
	public function sanitizeValues(array $row): array
104
	{
105
		++$this->rowNo;
106
		$this->colNo = 1;
107
108
		foreach ($this->fields as $dbKey => $fieldModel) {
109
			$idKey = 'id';
110
			if ($fieldModel->get('source_field_name')) {
111
				$name = $fieldModel->get('source_field_name') . $fieldModel->getModuleName();
112
				$idKey = $name . $idKey;
113
				$dbKey = $name . $fieldModel->getName();
114
			}
115
116
			$this->putDataIntoSpreadsheet($fieldModel, $row[$dbKey], $row[$idKey] ?? 0);
117
		}
118
119
		return [];
120
	}
121
122
	/**
123
	 * Put data into spread sheet.
124
	 *
125
	 * @param Vtiger_Field_Model $fieldModel
126
	 * @param mixed              $value
127
	 * @param int                $id
128
	 *
129
	 * @return void
130
	 */
131
	public function putDataIntoSpreadsheet(Vtiger_Field_Model $fieldModel, $value, int $id)
132
	{
133
		switch ($fieldModel->getFieldDataType()) {
134
			case 'integer':
135
			case 'double':
136
			case 'currency':
137
				$type = is_numeric($value) ? \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_NUMERIC : \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING;
138
				$this->workSheet->setCellValueExplicitByColumnAndRow($this->colNo, $this->rowNo, $value, $type);
139
				break;
140
			case 'date':
141
				if ($value) {
142
					$this->workSheet->setCellValueExplicitByColumnAndRow($this->colNo, $this->rowNo, \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($value), \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_NUMERIC);
143
					$this->workSheet->getStyleByColumnAndRow($this->colNo, $this->rowNo)->getNumberFormat()->setFormatCode('DD/MM/YYYY');
144
				} else {
145
					$this->workSheet->setCellValueExplicitByColumnAndRow($this->colNo, $this->rowNo, '', \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
146
				}
147
				break;
148
			case 'datetime':
149
				if ($value) {
150
					$this->workSheet->setCellValueExplicitByColumnAndRow($this->colNo, $this->rowNo, \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($value), \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_NUMERIC);
151
					$this->workSheet->getStyleByColumnAndRow($this->colNo, $this->rowNo)->getNumberFormat()->setFormatCode('DD/MM/YYYY HH:MM:SS');
152
				} else {
153
					$this->workSheet->setCellValueExplicitByColumnAndRow($this->colNo, $this->rowNo, '', \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
154
				}
155
				break;
156
			default:
157
				$displayValue = $this->getDisplayValue($fieldModel, $value, $id, []) ?: '';
158
				$this->workSheet->setCellValueExplicitByColumnAndRow($this->colNo, $this->rowNo, $displayValue, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
159
		}
160
		++$this->colNo;
161
	}
162
163
	/** {@inheritdoc} */
164
	public function sanitizeInventoryValues(array $inventoryRow, array $inventoryFields): array
165
	{
166
		++$this->invNo;
167
		$this->workSheet->setCellValueExplicitByColumnAndRow($this->colNo, $this->rowNo, $this->invNo, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_NUMERIC);
168
		++$this->colNo;
169
		foreach ($inventoryFields as $columnName => $field) {
170
			$value = $inventoryRow[$columnName] ?? '';
171
			if (\in_array($field->getType(), ['Name', 'Reference', 'Currency', 'Value', 'Unit', 'Boolean', 'Comment', 'Picklist', 'PicklistField', 'DiscountMode', 'TaxMode'])) {
172
				$this->workSheet->setCellValueExplicitByColumnAndRow($this->colNo, $this->rowNo, $field->getDisplayValue($value, $inventoryRow, true), \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
173
			} elseif ('Date' === $field->getType()) {
174
				if ($value) {
175
					$this->workSheet->setCellValueExplicitByColumnAndRow($this->colNo, $this->rowNo, \PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel($value), \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_NUMERIC);
176
					$this->workSheet->getStyleByColumnAndRow($this->colNo, $this->rowNo)->getNumberFormat()->setFormatCode('DD/MM/YYYY');
177
				} else {
178
					$this->workSheet->setCellValueExplicitByColumnAndRow($this->colNo, $this->rowNo, '', \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
179
				}
180
			} else {
181
				$type = is_numeric($value) ? \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_NUMERIC : \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING;
182
				$this->workSheet->setCellValueExplicitByColumnAndRow($this->colNo, $this->rowNo, $value, $type);
183
			}
184
			++$this->colNo;
185
			foreach ($field->getCustomColumn() as $customColumnName => $dbType) {
186
				$valueParam = $inventoryRow[$customColumnName] ?? '';
187
				if ('currencyparam' === $customColumnName) {
188
					$field = $inventoryFields['currency'];
189
					$valueData = $field->getCurrencyParam([], $valueParam);
190
					if (\is_array($valueData)) {
191
						$valueNewData = [];
192
						foreach ($valueData as $currencyId => $data) {
193
							$currencyName = \App\Fields\Currency::getById($currencyId)['currency_name'];
194
							$valueNewData[$currencyName] = $data;
195
						}
196
						$valueParam = \App\Json::encode($valueNewData);
197
					}
198
				}
199
				$this->workSheet->setCellValueExplicitByColumnAndRow($this->colNo, $this->rowNo, $valueParam, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING);
200
				++$this->colNo;
201
			}
202
		}
203
		return [];
204
	}
205
}
206