Completed
Push — middleware-wip ( 6cd994...b65ea9 )
by Romain
07:11
created

FormMetadataObject::deepClone()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.2
c 0
b 0
f 0
cc 4
eloc 7
nc 4
nop 2
1
<?php
2
/*
3
 * 2017 Romain CANON <[email protected]>
4
 *
5
 * This file is part of the TYPO3 FormZ project.
6
 * It is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU General Public License, either
8
 * version 3 of the License, or any later version.
9
 *
10
 * For the full copyright and license information, see:
11
 * http://www.gnu.org/licenses/gpl-3.0.html
12
 */
13
14
namespace Romm\Formz\Domain\Model\DataObject;
15
16
use Romm\Formz\Exceptions\EntryNotFoundException;
17
use TYPO3\CMS\Core\Type\TypeInterface;
18
use TYPO3\CMS\Core\Utility\ArrayUtility;
19
20
/**
21
 * Store and retrieve arbitrary data using the setter/getter functions.
22
 */
23
class FormMetadataObject implements TypeInterface
24
{
25
    /**
26
     * @var array
27
     */
28
    protected $metadata = [];
29
30
    /**
31
     * @param array $data
32
     */
33
    public function __construct($data = null)
34
    {
35
        if ($data) {
36
            $data = unserialize($data);
37
38
            if (is_array($data)
39
                && isset($data['metadata'])
40
            ) {
41
                $this->metadata = $data['metadata'];
42
            }
43
        }
44
    }
45
46
    /**
47
     * @param string $key
48
     * @return mixed
49
     * @throws EntryNotFoundException
50
     */
51
    public function get($key)
52
    {
53
        if (false === $this->has($key)) {
54
            throw EntryNotFoundException::metadataNotFound($key);
55
        }
56
57
        return ArrayUtility::getValueByPath($this->metadata, $key, '.');
58
    }
59
60
    /**
61
     * @param string $key
62
     * @return bool
63
     */
64
    public function has($key)
65
    {
66
        return ArrayUtility::isValidPath($this->metadata, $key, '.');
67
    }
68
69
    /**
70
     * @param string $key
71
     * @param mixed  $value
72
     */
73
    public function set($key, $value)
74
    {
75
        $this->metadata = ArrayUtility::setValueByPath($this->metadata, $key, $value, '.');
76
    }
77
78
    /**
79
     * @param string $key
80
     */
81
    public function remove($key)
82
    {
83
        if ($this->has($key)) {
84
            $this->metadata = ArrayUtility::removeByPath($this->metadata, $key, '.');
85
        }
86
    }
87
88
    /**
89
     * @return array
90
     */
91
    public function getMetadata()
92
    {
93
        return $this->metadata;
94
    }
95
96
    /**
97
     * @return string
98
     */
99
    public function __toString()
100
    {
101
        return serialize(['metadata' => $this->metadata]);
102
    }
103
104
    /**
105
     * @see deepClone()
106
     */
107
    public function __clone()
108
    {
109
        $this->deepClone($this->metadata);
110
    }
111
112
    /**
113
     * When the metadata is fetched from persistence, the `metadata` array can
114
     * contain object instances, meaning that by default the original references
115
     * to these objects are used in the clean properties, resulting in the
116
     * object modification not being detected.
117
     *
118
     * In this function, we clone every object that is found, to solve the issue
119
     * above.
120
     *
121
     * @param mixed $entry
122
     * @param array $path
123
     */
124
    protected function deepClone($entry, array $path = [])
125
    {
126
        if (is_array($entry)) {
127
            foreach ($entry as $key => $item) {
128
                $path[] = $key;
129
                $this->deepClone($item, $path);
130
            }
131
        } elseif (is_object($entry)) {
132
            $this->set(implode('.', $path), clone $entry);
133
        }
134
    }
135
}
136