* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Sonata\Exporter\Writer; /** * Generate a Xml Excel file. * * @author Vincent Touzet */ class XmlExcelWriter implements WriterInterface { /** * @var string|null */ protected $filename = null; /** * @var resource|null */ protected $file = null; /** * @var bool */ protected $showHeaders; /** * @var mixed|null */ protected $columnsType = null; /** * @var int */ protected $position = 0; /** * @var string */ protected $header = ''; protected $footer = '
'; /** * @param string $filename * @param bool $showHeaders * @param mixed $columnsType Define cells type to use * If string: force all cells to the given type. e.g: 'Number' * If array: force only given cells. e.g: array('ean'=>'String', 'price'=>'Number') * If null: will guess the type. 'Number' if value is numeric, 'String' otherwise */ public function __construct($filename, $showHeaders = true, $columnsType = null) { $this->filename = $filename; $this->showHeaders = $showHeaders; $this->columnsType = $columnsType; if (is_file($filename)) { throw new \RuntimeException(sprintf('The file %s already exist', $filename)); } } public function open() { $this->file = fopen($this->filename, 'w'); fwrite($this->file, $this->header); } /** * @param array $data */ public function write(array $data) { if (0 == $this->position && $this->showHeaders) { $header = array_keys($data); fwrite($this->file, $this->getXmlString($header)); ++$this->position; } fwrite($this->file, $this->getXmlString($data)); ++$this->position; } public function close() { fwrite($this->file, $this->footer); fclose($this->file); } /** * Prepare and return XML string for MS Excel XML from array. * * @param array $fields * * @return string */ private function getXmlString(array $fields = []) { $xmlData = []; $xmlData[] = ''; foreach ($fields as $key => $value) { $value = htmlspecialchars($value); $value = str_replace(["\r\n", "\r", "\n"], ' ', $value); $dataType = 'String'; if (0 != $this->position || !$this->showHeaders) { $dataType = $this->getDataType($key, $value); } $xmlData[] = ''.$value.''; } $xmlData[] = ''; return implode('', $xmlData); } /** * @param string $key * @param string $value * * @return string */ private function getDataType($key, $value) { $dataType = null; if (null !== $this->columnsType) { if (\is_string($this->columnsType)) { $dataType = $this->columnsType; } elseif (\is_array($this->columnsType)) { if (\array_key_exists($key, $this->columnsType)) { $dataType = $this->columnsType[$key]; } } } if (null === $dataType) { // guess the type if (is_numeric($value)) { $dataType = 'Number'; } else { $dataType = 'String'; } } return $dataType; } } class_exists(\Exporter\Writer\XmlExcelWriter::class);