PhpWriter::write()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 8
c 1
b 0
f 0
nc 2
nop 2
dl 0
loc 12
ccs 9
cts 9
cp 1
crap 2
rs 10
1
<?php
2
3
namespace ConfigWriter\Writers;
4
5
use ConfigWriter\Exceptions\WriteException;
6
use ConfigWriter\AbstractConfig;
7
use ConfigWriter\Record;
8
9
/**
10
 * Configuration writer for PHP.
11
 *
12
 * @since 2.0.0
13
 *
14
 * @author Filip Š <[email protected]>
15
 *
16
 * @license MIT
17
 *
18
 * @package ConfigWriter
19
 */
20
class PhpWriter implements WriterInterface
21
{
22
    /**
23
     * Stores default configuration options.
24
     *
25
     * @var array
26
     */
27
    protected $options = [
28
        'indentation' => '    ',
29
        'eol' => "\n",
30
        'boolean' => [
31
            'true' => 'true',
32
            'false' => 'false',
33
        ],
34
        'string' => [ 'quotes' => '\'' ],
35
        'array' => [
36
            'open' => '[',
37
            'close' => ']',
38
            'comma' => true,
39
        ],
40
        'comments' => [
41
            'section' => 'c-style',
42
            'record' => 'c-style',
43
        ],
44
    ];
45
46
    /**
47
     * Returns parsable string representation of a variable.
48
     *
49
     * @param mixed   $variable Variable for exporting
50
     * @param array   $options  Options for exporting
51
     *   * indentation: &nbsp;&nbsp;&nbsp;&nbsp; (string, default) - Indenttion string
52
     *   * eol:         \n                       (string, default) - End of line string
53
     *   * boolean (array)
54
     *     * true:  true  (string, default) - The true keyword
55
     *     * false: false (string, default) - The false keyword
56
     *   * string (array)
57
     *     * quotes: ' (string, default) - The string quotes
58
     *   * array (array)
59
     *     * open:  [    (string, default)  - The array open tag
60
     *     * close: ]    (string, default)  - The array close tag
61
     *     * comma: true (boolean, default) - Comma at the end of array
62
     *   * comments (array)
63
     *     * section: c-style ((c-style, perl-style, multi-line, doc-block), default) - The comment style for sections
64
     *     * record:  c-style ((c-style, perl-style, multi-line, doc-block), default) - The comment style for records
65
     * @param string  $level    Indentation level
66
     * @param boolean $comma    If comma should be added to result
67
     * @param string  $section  Comment of section
68
     *
69
     * @return string Exported data
70
     */
71 1
    protected function export($variable, $options = [], $level = 0, $comma = true, $section = '')
72
    {
73 1
        if ($variable instanceof AbstractConfig) {
74 1
            $value = $variable->data;
75 1
            $comment = $variable->comment;
76 1
        } elseif ($variable instanceof Record) {
77 1
            $value = $variable->value;
78 1
            $comment = $variable->comment;
79
        } else {
80 1
            $value = $variable;
81 1
            $comment = null;
82
        }
83
84 1
        switch (gettype($value)) {
85 1
            case 'boolean':
86 1
                $result = $value
87 1
                    ? $options['boolean']['true']
88 1
                    : $options['boolean']['false'];
89
90 1
                $result .= $comma
91 1
                    ? ','
92 1
                    : '';
93
94 1
                $result .= $comment
95 1
                    ? ' ' . $this->comment($comment, $options['comments']['record'])
96 1
                    : '';
97
98 1
                return $result;
99
100 1
            case 'string':
101 1
                if ($section) {
102 1
                    $result = $this->comment($section, $options['comments']['section'])
103 1
                        . $options['eol']
104 1
                        . str_repeat($options['indentation'], $level);
0 ignored issues
show
Bug introduced by
It seems like $level can also be of type string; however, parameter $multiplier of str_repeat() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

104
                        . str_repeat($options['indentation'], /** @scrutinizer ignore-type */ $level);
Loading history...
105
                } else {
106 1
                    $result = '';
107
                }
108
109 1
                $result .= $options['string']['quotes']
110 1
                    . addcslashes($value, "\\\$\"\r\n\t\v\f")
111 1
                    . $options['string']['quotes'];
112
113 1
                $result .= $comma
114 1
                    ? ','
115 1
                    : '';
116
117 1
                if (!$variable instanceof AbstractConfig && $comment) {
118 1
                    $result .= $comment
119 1
                    ? ' ' . $this->comment($comment, $options['comments']['record'])
120 1
                    : '';
121
                }
122
123 1
                return $result;
124
125 1
            case 'array':
126 1
                $indexed = array_keys($value) === range(0, (count($value) - 1));
127 1
                $keys = array_keys($value);
128 1
                $last = end($keys);
129 1
                $eol = $options['eol'];
130
131 1
                $arr = [];
132 1
                foreach ($value as $key => $val) {
133 1
                    if ($key !== $last || $options['array']['comma'] !== false) {
134 1
                        $comma = true;
135
                    } else {
136
                        $comma = false;
137
                    }
138
139 1
                    $arr[] = str_repeat($options['indentation'], $level)
140
                        . (
141 1
                            $indexed ? '' : $this->export(
142 1
                                $key,
143
                                $options,
144
                                $level,
145 1
                                false,
146 1
                                ($val instanceof AbstractConfig ? $val->comment : '')
147 1
                            ) . ' => '
148
                        )
149 1
                        . $this->export($val, $options, ($level + 1), true);
150
                }
151
152
                return '['
153 1
                    . $eol
154 1
                    . implode(
155 1
                        $eol,
156
                        $arr
157
                    )
158 1
                    . $eol
159 1
                    . str_repeat($options['indentation'], ($level - 1))
160 1
                    . ']'
161
                    . (
162 1
                        $options['array']['comma'] && !is_array($variable)
163 1
                        ? ','
164 1
                        : ''
165
                    );
166
167
            default:
168 1
                $result = var_export($value, true);
169
170 1
                $result .= $comma
171 1
                    ? ','
172 1
                    : '';
173
174 1
                $result .= $comment
175 1
                    ? ' ' . $this->comment($comment, $options['comments']['record'])
176 1
                    : '';
177
178 1
                return $result;
179
        }
180
    }
181
182
    /**
183
     * Returns comment of chosen style.
184
     *
185
     * @param string $data  Comment data.
186
     * @param array  $style Comment style.
187
     *
188
     * @return string Styled comment
189
     */
190 6
    protected function comment($data, $style)
191
    {
192 6
        if ($style === 'c-style') {
0 ignored issues
show
introduced by
The condition $style === 'c-style' is always false.
Loading history...
193 2
            $format = '// %s';
194 4
        } elseif ($style === 'perl-style') {
0 ignored issues
show
introduced by
The condition $style === 'perl-style' is always false.
Loading history...
195 1
            $format = '# %s';
196 3
        } elseif ($style === 'multi-line') {
0 ignored issues
show
introduced by
The condition $style === 'multi-line' is always false.
Loading history...
197 1
            $format = '/* %s */';
198 2
        } elseif ($style === 'doc-block') {
0 ignored issues
show
introduced by
The condition $style === 'doc-block' is always false.
Loading history...
199 1
            $format = '/** %s */';
200
        } else {
201 1
            $format = '// %s';
202
        }
203
204 6
        return sprintf($format, $data);
205
    }
206
207
    /**
208
     * {@inheritDoc}
209
     *
210
     * Returns configuration as PHP array.
211
     */
212 1
    public function write(AbstractConfig $config, $options = [])
213
    {
214 1
        $options = array_replace_recursive($this->options, $options);
215 1
        $eol = $options['eol'];
216
217 1
        $converted = '<?php' . $eol . $eol;
218 1
        $converted .= (!empty($config->comment) ? $config->comment . $eol . $eol : '');
219 1
        $converted .= 'return ';
220 1
        $converted .= $this->export($config->data, $options, 1);
221 1
        $converted .= ';' . $eol;
222
223 1
        return $converted;
224
    }
225
226
    /**
227
     * {@inheritDoc}
228
     */
229 1
    public static function getSupportedExtensions()
230
    {
231 1
        return ['php'];
232
    }
233
}
234