Completed
Push — master ( 9d4592...64b389 )
by Andreas
05:50
created

dbobject   B

Complexity

Total Complexity 36

Size/Duplication

Total Lines 188
Duplicated Lines 5.32 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 85.59%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 10
loc 188
ccs 95
cts 111
cp 0.8559
rs 8.8
c 1
b 0
f 0
wmc 36
lcom 1
cbo 4

8 Methods

Rating   Name   Duplication   Size   Complexity  
A injectObjectManager() 0 8 2
A __get_changed_associations() 0 4 1
A __debugInfo() 0 16 2
C __set() 5 65 17
D __get() 5 35 9
A __isset() 0 4 1
A populate_from_entity() 0 8 2
A initialize() 0 7 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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\Common\Persistence\ObjectManagerAware;
11
use Doctrine\Common\Persistence\ObjectManager;
12
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
13
use midgard_datetime;
14
15
abstract class dbobject implements ObjectManagerAware
16
{
17
    protected $guid = '';
18
19
    /**
20
     *
21
     * @var ClassMetadata
22
     */
23
    protected $cm;
24
25
    /**
26
     * Simple map of association fields changed during the object's lifetime
27
     *
28
     * We need this for some workarounds for proxy-related problems during changeset calculation
29
     *
30
     * @var array
31
     */
32
    protected $changed_associations = array();
33
34
    /**
35
     * {@inheritDoc}
36
     */
37 77
    public function injectObjectManager(ObjectManager $objectmanager, ClassMetadata $classmetadata)
38
    {
39 77
        if ($objectmanager !== connection::get_em()) {
40
            throw new \RuntimeException("Trying to use midgard_dbobject with different ObjectManager instances");
41
        }
42
43 77
        $this->cm = $classmetadata;
44 77
    }
45
46
    /**
47
     * @return array
48
     */
49 26
    public function __get_changed_associations()
50
    {
51 26
        return $this->changed_associations;
52
    }
53
54
    /**
55
     * Filter out internal stuff for var_dump
56
     *
57
     * This is not 100% accurate right now (e.g. metadata is not handled totally correctly), but at least it
58
     * prevents killing the server by dumping recursively linked EntityManagers and the like
59
     *
60
     * @return array
61
     */
62
    public function __debugInfo()
63
    {
64
        $this->initialize();
65
        $properties = array_merge($this->cm->getFieldNames(), $this->cm->getAssociationNames(), array_keys($this->cm->midgard['field_aliases']));
0 ignored issues
show
Bug introduced by
Accessing midgard on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
66
        $properties = array_filter($properties, function($input)
67
        {
68
            return (strpos($input, 'metadata_') === false);
69
        });
70
        $ret = array();
71
        foreach ($properties as $property)
72
        {
73
            $ret[$property] = $this->__get($property);
74
        }
75
76
        return $ret;
77
    }
78
79 111
    public function __set($field, $value)
80
    {
81 111
        $this->initialize();
82
83 111 View Code Duplication
        if (   !$this->cm->hasField($field)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
84 111
            && array_key_exists($field, $this->cm->midgard['field_aliases']))
0 ignored issues
show
Bug introduced by
Accessing midgard on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
85 111
        {
86
            $field = $this->cm->midgard['field_aliases'][$field];
0 ignored issues
show
Bug introduced by
Accessing midgard on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
87
        }
88 111
        if ($this->cm->isSingleValuedAssociation($field))
89 111
        {
90
            // mgd api only allows setting links identifiers, doctrine wants objects,
91
            // so it seems we need an expensive and pretty useless conversion..
92 52
            if (empty($value))
93 52
            {
94 35
                $value = null;
95 35
            }
96
            else
97
            {
98 31
                if (   !is_object($this->$field)
99 31
                    || $this->$field->id != $value)
100 31
                {
101 31
                    $this->changed_associations[$field] = true;
102 31
                }
103 31
                $classname = $this->cm->getAssociationTargetClass($field);
104 31
                $value = connection::get_em()->getReference($classname, $value);
105
            }
106 52
        }
107 111
        else if ($this->cm->hasField($field))
108 111
        {
109 110
            $mapping = $this->cm->getFieldMapping($field);
110
111 110
            if (   $mapping['type'] === 'string'
112 110
                || $mapping['type'] == 'text')
113 110
            {
114 109
                $value = (string) $value;
115 109
            }
116 105
            else if ($mapping['type'] === 'integer')
117 105
            {
118 105
                $value = (int) $value;
119 105
            }
120 95
            else if ($mapping['type'] === 'boolean')
121 95
            {
122 40
                $value = (boolean) $value;
123 40
            }
124 95
            else if ($mapping['type'] === 'float')
125 95
            {
126 8
                $value = (float) $value;
127 8
            }
128 95
            else if ($mapping['type'] === 'midgard_datetime')
129 95
            {
130 95
                if (   is_string($value)
131 95
                    && $value !== '0000-00-00 00:00:00')
132 95
                {
133 7
                    $value = new midgard_datetime($value);
134 7
                }
135 94
                else if (!($value instanceof midgard_datetime))
136 94
                {
137 1
                    $value = new midgard_datetime('0001-01-01 00:00:00');
138 1
                }
139 95
            }
140 110
        }
141
142 111
        $this->$field = $value;
143 111
    }
144
145 119
    public function __get($field)
146
    {
147 119
        $this->initialize();
148
149 119 View Code Duplication
        if (   !$this->cm->hasField($field)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
150 119
            && array_key_exists($field, $this->cm->midgard['field_aliases']))
0 ignored issues
show
Bug introduced by
Accessing midgard on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
151 119
        {
152
            $field = $this->cm->midgard['field_aliases'][$field];
0 ignored issues
show
Bug introduced by
Accessing midgard on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
153
        }
154
155 119
        if ($this->cm->isSingleValuedAssociation($field))
156 119
        {
157
            // mgd api only allows returning link identifiers, doctrine has objects,
158
            // so it seems we need a pretty useless conversion..
159 93
            if (is_object($this->$field))
160 93
            {
161 31
                return (int) $this->$field->id;
162
            }
163 93
            return 0;
164
        }
165 118
        if (   $this->$field === null
166 118
            && $this->cm->isIdentifier($field))
167 118
        {
168 96
            return 0;
169
        }
170 116
        if (   $this->$field instanceof midgard_datetime
171 116
            && $this->$field->format('U') == -62169984000)
172 116
        {
173
            //This is mainly needed for working with converted Legacy databases. Midgard2 somehow handles this internally
174
            //@todo Find a nicer solution and research how QB handles this
175 1
            $this->$field->setDate(1, 1, 1);
176 1
        }
177
178 116
        return $this->$field;
179
    }
180
181 107
    public function __isset($field)
182
    {
183 107
        return property_exists($this, $field);
184
    }
185
186 50
    protected function populate_from_entity(dbobject $entity)
187
    {
188 50
        $this->initialize();
189 50
        foreach ($this->cm->reflFields as $name => $field)
0 ignored issues
show
Bug introduced by
Accessing reflFields on the interface Doctrine\Common\Persistence\Mapping\ClassMetadata suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
190
        {
191 50
            $this->$name = $entity->$name;
192 50
        }
193 50
    }
194
195 123
    protected function initialize()
196
    {
197 123
        if ($this->cm === null)
198 123
        {
199 119
            $this->cm = connection::get_em()->getClassMetadata(get_class($this));
200 119
        }
201 123
    }
202
}
203