1<?php
2/**
3 * Zend Framework (http://framework.zend.com/)
4 *
5 * @link      http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license   http://framework.zend.com/license/new-bsd New BSD License
8 */
9
10namespace Zend\Config\Writer;
11
12use XMLWriter;
13use Zend\Config\Exception;
14
15class Xml extends AbstractWriter
16{
17    /**
18     * processConfig(): defined by AbstractWriter.
19     *
20     * @param  array $config
21     * @return string
22     */
23    public function processConfig(array $config)
24    {
25        $writer = new XMLWriter();
26        $writer->openMemory();
27        $writer->setIndent(true);
28        $writer->setIndentString(str_repeat(' ', 4));
29
30        $writer->startDocument('1.0', 'UTF-8');
31        $writer->startElement('zend-config');
32
33        foreach ($config as $sectionName => $data) {
34            if (!is_array($data)) {
35                $writer->writeElement($sectionName, (string) $data);
36            } else {
37                $this->addBranch($sectionName, $data, $writer);
38            }
39        }
40
41        $writer->endElement();
42        $writer->endDocument();
43
44        return $writer->outputMemory();
45    }
46
47    /**
48     * Add a branch to an XML object recursively.
49     *
50     * @param  string    $branchName
51     * @param  array     $config
52     * @param  XMLWriter $writer
53     * @return void
54     * @throws Exception\RuntimeException
55     */
56    protected function addBranch($branchName, array $config, XMLWriter $writer)
57    {
58        $branchType = null;
59
60        foreach ($config as $key => $value) {
61            if ($branchType === null) {
62                if (is_numeric($key)) {
63                    $branchType = 'numeric';
64                } else {
65                    $writer->startElement($branchName);
66                    $branchType = 'string';
67                }
68            } elseif ($branchType !== (is_numeric($key) ? 'numeric' : 'string')) {
69                throw new Exception\RuntimeException('Mixing of string and numeric keys is not allowed');
70            }
71
72            if ($branchType === 'numeric') {
73                if (is_array($value)) {
74                    $this->addBranch($branchName, $value, $writer);
75                } else {
76                    $writer->writeElement($branchName, (string) $value);
77                }
78            } else {
79                if (is_array($value)) {
80                    $this->addBranch($key, $value, $writer);
81                } else {
82                    $writer->writeElement($key, (string) $value);
83                }
84            }
85        }
86
87        if ($branchType === 'string') {
88            $writer->endElement();
89        }
90    }
91}
92