Passed
Push — master ( d1d055...513454 )
by Andreas
14:02
created

dbobject::initialize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
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 82
    public function injectObjectManager(ObjectManager $objectmanager, ClassMetadata $classmetadata)
34
    {
35 82
        if ($objectmanager !== connection::get_em()) {
0 ignored issues
show
introduced by
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 82
        $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 126
    public function __set($field, $value)
71
    {
72 126
        $this->initialize();
73
74 126
        if (   !$this->cm->hasField($field)
75 126
            && isset($this->cm->midgard['field_aliases'][$field])) {
76
            $field = $this->cm->midgard['field_aliases'][$field];
77
        }
78 126
        if ($this->cm->isSingleValuedAssociation($field)) {
79
            // mgd api only allows setting links identifiers, doctrine wants objects,
80
            // so it seems we need an expensive and pretty useless conversion..
81 57
            if (empty($value)) {
82 37
                $value = null;
83
            } else {
84 36
                if (   !\is_object($this->$field)
85 36
                    || $this->$field->id != $value) {
86 36
                    $this->changed_associations[$field] = true;
87
                }
88 36
                $classname = $this->cm->getAssociationTargetClass($field);
89 57
                $value = connection::get_em()->getReference($classname, $value);
90
            }
91 126
        } elseif ($this->cm->hasField($field)) {
92 125
            $mapping = $this->cm->getFieldMapping($field);
93
94 125
            if (   $mapping['type'] === 'string'
95 125
                || $mapping['type'] == 'text') {
96 124
                $value = (string) $value;
97 120
            } elseif ($mapping['type'] === 'integer') {
98 120
                $value = (int) $value;
99 120
                if ($value === 0 && $this->cm->isIdentifier($field)) {
100 120
                    $value = null;
101
                }
102 101
            } elseif ($mapping['type'] === 'boolean') {
103 42
                $value = (boolean) $value;
104 101
            } elseif ($mapping['type'] === 'float') {
105 8
                $value = (float) $value;
106 101
            } elseif (in_array($mapping['type'], ['datetime', 'date'])) {
107 101
                if (   \is_string($value)
108 101
                    && $value !== '0000-00-00 00:00:00') {
109 7
                    $value = new midgard_datetime($value);
110 100
                } elseif (!($value instanceof midgard_datetime)) {
111 1
                    $value = new midgard_datetime('0001-01-01 00:00:00');
112
                }
113
            }
114
        }
115
116 126
        $this->$field = $value;
117
    }
118
119 137
    public function __get($field)
120
    {
121 137
        $this->initialize();
122
123 137
        if (   !$this->cm->hasField($field)
124 137
            && isset($this->cm->midgard['field_aliases'][$field])) {
125
            $field = $this->cm->midgard['field_aliases'][$field];
126
        }
127
128 137
        if ($this->cm->isSingleValuedAssociation($field)) {
129
            // mgd api only allows returning link identifiers, doctrine has objects,
130
            // so it seems we need a pretty useless conversion..
131 108
            if (is_object($this->$field)) {
132 36
                return (int) $this->$field->id;
133
            }
134 108
            return 0;
135
        }
136 136
        if (   $this->$field === null
137 136
            && $this->cm->isIdentifier($field)) {
138 103
            return 0;
139
        }
140 134
        if (   $this->$field instanceof midgard_datetime
141 134
            && $this->$field->format('U') == -62169984000) {
142
            //This is mainly needed for working with converted Legacy databases. Midgard2 somehow handles this internally
143
            //@todo Find a nicer solution and research how QB handles this
144 1
            $this->$field->setDate(1, 1, 1);
145
        }
146
147 134
        return $this->$field;
148
    }
149
150 123
    public function __isset($field)
151
    {
152 123
        return property_exists($this, $field);
153
    }
154
155 54
    protected function populate_from_entity(dbobject $entity)
156
    {
157 54
        $this->initialize();
158 54
        foreach ($this->cm->reflFields as $name => $field) {
159 54
            $this->$name = $entity->$name;
160
        }
161
    }
162
163 143
    protected function initialize()
164
    {
165 143
        $this->cm ??= connection::get_em()->getClassMetadata(get_class($this));
166
    }
167
}
168