| 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
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 |