getFilename()); foreach ($model->toArray() as $search => $replace) { if (\is_array($replace)) { // TODO tax rows continue; } $replace = $xmlEscaper->escape($replace); $replace = preg_replace('/\n|\r\n?/', '', $replace); $template->setValue($search, $replace); } try { $template->cloneRow('entry.description', \count($model->getCalculator()->getEntries())); } catch (OfficeException $ex) { try { $template->cloneRow('entry.row', \count($model->getCalculator()->getEntries())); } catch (OfficeException $ex) { @trigger_error('Invoice document did not contain a clone row, was that on purpose?'); } } $i = 1; foreach ($model->getCalculator()->getEntries() as $entry) { $values = $model->itemToArray($entry); foreach ($values as $search => $replace) { $replace = $xmlEscaper->escape($replace); $replace = preg_replace('/\n|\r\n?/', '', $replace); $template->setValue($search . '#' . $i, $replace); } $i++; } $cacheFile = @tempnam(sys_get_temp_dir(), 'kimai-invoice-docx'); if (false === $cacheFile) { throw new \Exception('Could not open temporary file'); } $template->saveAs($cacheFile); clearstatcache(true, $cacheFile); $filename = $this->buildFilename($model) . '.' . $document->getFileExtension(); return $this->getFileResponse(new Stream($cacheFile), $filename); } protected function getFileExtensions(): array { return ['.docx']; } protected function getContentType(): string { return 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; } }