Issues (134)

src/api/dbobject.php (1 issue)

Severity
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
The condition $objectmanager !== midga...ge\connection::get_em() is always true.
Loading history...
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