1 | <?php |
||
2 | /** |
||
3 | * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/ |
||
4 | * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/ |
||
5 | * @license http://www.gnu.org/licenses/gpl.html GNU General Public License |
||
6 | */ |
||
7 | namespace midgard\portable\api; |
||
8 | |||
9 | use midgard\portable\storage\connection; |
||
10 | use Doctrine\Persistence\ObjectManager; |
||
11 | use Doctrine\Persistence\Mapping\ClassMetadata; |
||
12 | use midgard_datetime; |
||
13 | |||
14 | abstract class dbobject |
||
15 | { |
||
16 | protected string $guid = ''; |
||
17 | |||
18 | /** |
||
19 | * @var \midgard\portable\mapping\classmetadata |
||
20 | */ |
||
21 | protected $cm; |
||
22 | |||
23 | /** |
||
24 | * Simple map of association fields changed during the object's lifetime |
||
25 | * |
||
26 | * We need this for some workarounds for proxy-related problems during changeset calculation |
||
27 | */ |
||
28 | protected array $changed_associations = []; |
||
29 | |||
30 | /** |
||
31 | * {@inheritDoc} |
||
32 | */ |
||
33 | 83 | public function injectObjectManager(ObjectManager $objectmanager, ClassMetadata $classmetadata) |
|
34 | { |
||
35 | 83 | if ($objectmanager !== connection::get_em()) { |
|
0 ignored issues
–
show
introduced
by
![]() |
|||
36 | throw new \RuntimeException("Trying to use midgard_dbobject with different ObjectManager instances"); |
||
37 | } |
||
38 | |||
39 | 83 | $this->cm = $classmetadata; |
|
40 | } |
||
41 | |||
42 | 27 | public function __get_changed_associations() : array |
|
43 | { |
||
44 | 27 | return $this->changed_associations; |
|
45 | } |
||
46 | |||
47 | /** |
||
48 | * Filter out internal stuff for var_dump |
||
49 | * |
||
50 | * This is not 100% accurate right now (e.g. metadata is not handled totally correctly), but at least it |
||
51 | * prevents killing the server by dumping recursively linked EntityManagers and the like |
||
52 | * |
||
53 | * @return array |
||
54 | */ |
||
55 | 1 | public function __debugInfo() |
|
56 | { |
||
57 | 1 | $this->initialize(); |
|
58 | 1 | $properties = array_merge($this->cm->getFieldNames(), $this->cm->getAssociationNames(), array_keys($this->cm->midgard['field_aliases'])); |
|
59 | 1 | $properties = array_filter($properties, function ($input) { |
|
60 | 1 | return !str_contains($input, 'metadata_'); |
|
61 | 1 | }); |
|
62 | 1 | $ret = []; |
|
63 | 1 | foreach ($properties as $property) { |
|
64 | 1 | $ret[$property] = $this->__get($property); |
|
65 | } |
||
66 | |||
67 | 1 | return $ret; |
|
68 | } |
||
69 | |||
70 | 128 | public function __set($field, $value) |
|
71 | { |
||
72 | 128 | $this->initialize(); |
|
73 | |||
74 | 128 | if ( !$this->cm->hasField($field) |
|
75 | 128 | && isset($this->cm->midgard['field_aliases'][$field])) { |
|
76 | $field = $this->cm->midgard['field_aliases'][$field]; |
||
77 | } |
||
78 | 128 | if ($this->cm->isSingleValuedAssociation($field)) { |
|
79 | 59 | if ($this->cm->midgard['links_as_entities']) { |
|
80 | 2 | $this->$field = $value; |
|
81 | 2 | return; |
|
82 | } |
||
83 | // legacy mgd api: only setting link identifier |
||
84 | 57 | if (empty($value)) { |
|
85 | 37 | $value = null; |
|
86 | } else { |
||
87 | 36 | if ( !\is_object($this->$field) |
|
88 | 36 | || $this->$field->id != $value) { |
|
89 | 36 | $this->changed_associations[$field] = true; |
|
90 | } |
||
91 | 36 | $classname = $this->cm->getAssociationTargetClass($field); |
|
92 | 57 | $value = connection::get_em()->getReference($classname, $value); |
|
93 | } |
||
94 | 127 | } elseif ($this->cm->hasField($field)) { |
|
95 | 126 | $mapping = $this->cm->getFieldMapping($field); |
|
96 | |||
97 | 126 | if ( $mapping['type'] === 'string' |
|
98 | 126 | || $mapping['type'] == 'text') { |
|
99 | 125 | $value = (string) $value; |
|
100 | 121 | } elseif ($mapping['type'] === 'integer') { |
|
101 | 121 | $value = (int) $value; |
|
102 | 121 | if ($value === 0 && $this->cm->isIdentifier($field)) { |
|
103 | 121 | $value = null; |
|
104 | } |
||
105 | 102 | } elseif ($mapping['type'] === 'boolean') { |
|
106 | 42 | $value = (boolean) $value; |
|
107 | 102 | } elseif ($mapping['type'] === 'float') { |
|
108 | 8 | $value = (float) $value; |
|
109 | 102 | } elseif (in_array($mapping['type'], ['datetime', 'date'])) { |
|
110 | 102 | if ( \is_string($value) |
|
111 | 102 | && $value !== '0000-00-00 00:00:00') { |
|
112 | 7 | $value = new midgard_datetime($value); |
|
113 | 101 | } elseif (!($value instanceof midgard_datetime)) { |
|
114 | 1 | $value = new midgard_datetime('0001-01-01 00:00:00'); |
|
115 | } |
||
116 | } |
||
117 | } |
||
118 | |||
119 | 127 | $this->$field = $value; |
|
120 | } |
||
121 | |||
122 | 140 | public function __get($field) |
|
123 | { |
||
124 | 140 | $this->initialize(); |
|
125 | |||
126 | 140 | if ( !$this->cm->hasField($field) |
|
127 | 140 | && isset($this->cm->midgard['field_aliases'][$field])) { |
|
128 | $field = $this->cm->midgard['field_aliases'][$field]; |
||
129 | } |
||
130 | |||
131 | 140 | if ($this->cm->isSingleValuedAssociation($field)) { |
|
132 | 111 | if ($this->cm->midgard['links_as_entities']) { |
|
133 | 3 | return $this->$field; |
|
134 | } |
||
135 | // legacy mgd api: Only return link identifiers |
||
136 | 108 | if (is_object($this->$field)) { |
|
137 | 36 | return (int) $this->$field->id; |
|
138 | } |
||
139 | 108 | return 0; |
|
140 | } |
||
141 | 137 | if ( $this->$field === null |
|
142 | 137 | && $this->cm->isIdentifier($field)) { |
|
143 | 104 | return 0; |
|
144 | } |
||
145 | 135 | if ( $this->$field instanceof midgard_datetime |
|
146 | 135 | && $this->$field->format('U') == -62169984000) { |
|
147 | //This is mainly needed for working with converted Legacy databases. Midgard2 somehow handles this internally |
||
148 | //@todo Find a nicer solution and research how QB handles this |
||
149 | 1 | $this->$field->setDate(1, 1, 1); |
|
150 | } |
||
151 | |||
152 | 135 | return $this->$field; |
|
153 | } |
||
154 | |||
155 | 124 | public function __isset($field) |
|
156 | { |
||
157 | 124 | return property_exists($this, $field); |
|
158 | } |
||
159 | |||
160 | 54 | protected function populate_from_entity(dbobject $entity) |
|
161 | { |
||
162 | 54 | $this->initialize(); |
|
163 | 54 | foreach ($this->cm->reflFields as $name => $field) { |
|
164 | 54 | $this->$name = $entity->$name; |
|
165 | } |
||
166 | } |
||
167 | |||
168 | 146 | protected function initialize() |
|
169 | { |
||
170 | 146 | $this->cm ??= connection::get_em()->getClassMetadata(get_class($this)); |
|
171 | } |
||
172 | } |
||
173 |