1<?php
2/*
3 * This file is part of the GlobalState package.
4 *
5 * (c) Sebastian Bergmann <sebastian@phpunit.de>
6 *
7 * For the full copyright and license information, please view the LICENSE
8 * file that was distributed with this source code.
9 */
10
11namespace SebastianBergmann\GlobalState;
12
13/**
14 * Exports parts of a Snapshot as PHP code.
15 */
16class CodeExporter
17{
18    /**
19     * @param  Snapshot $snapshot
20     * @return string
21     */
22    public function constants(Snapshot $snapshot)
23    {
24        $result = '';
25
26        foreach ($snapshot->constants() as $name => $value) {
27            $result .= sprintf(
28                'if (!defined(\'%s\')) define(\'%s\', %s);' . "\n",
29                $name,
30                $name,
31                $this->exportVariable($value)
32            );
33        }
34
35        return $result;
36    }
37
38    /**
39     * @param  Snapshot $snapshot
40     * @return string
41     */
42    public function iniSettings(Snapshot $snapshot)
43    {
44        $result = '';
45
46        foreach ($snapshot->iniSettings() as $key => $value) {
47            $result .= sprintf(
48                '@ini_set(%s, %s);' . "\n",
49                $this->exportVariable($key),
50                $this->exportVariable($value)
51            );
52        }
53
54        return $result;
55    }
56
57    /**
58     * @param  mixed  $variable
59     * @return string
60     */
61    private function exportVariable($variable)
62    {
63        if (is_scalar($variable) || is_null($variable) ||
64            (is_array($variable) && $this->arrayOnlyContainsScalars($variable))) {
65            return var_export($variable, true);
66        }
67
68        return 'unserialize(' . var_export(serialize($variable), true) . ')';
69    }
70
71    /**
72     * @param  array $array
73     * @return bool
74     */
75    private function arrayOnlyContainsScalars(array $array)
76    {
77        $result = true;
78
79        foreach ($array as $element) {
80            if (is_array($element)) {
81                $result = self::arrayOnlyContainsScalars($element);
82            } elseif (!is_scalar($element) && !is_null($element)) {
83                $result = false;
84            }
85
86            if ($result === false) {
87                break;
88            }
89        }
90
91        return $result;
92    }
93}
94