Completed
Push — master ( 893c58...d623dc )
by Dmitry
03:33
created

Type::getName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Tarantool\Mapper\Schema;
4
5
use Tarantool\Mapper\Contracts;
6
use LogicException;
7
8
class Type implements Contracts\Type
9
{
10
    protected $convention;
11
    protected $properties = [];
12
    protected $types = [];
13
14
    protected $manager;
15
    protected $spaceId;
16
    protected $name;
17
18 25
    public function __construct(Contracts\Manager $manager, $name, array $properties, array $types)
19
    {
20 25
        $this->manager = $manager;
21 25
        $this->name = $name;
22 25
        $this->convention = $manager->getMeta()->getConvention();
23 25
        $this->spaceId = $manager->getSchema()->getSpaceId($name);
24
25 25
        $this->properties = $properties;
26 25
        $this->types = $types;
27 25
    }
28
29 25
    public function getSpace()
30
    {
31 25
        return $this->getManager()->getClient()->getSpace($this->name);
32
    }
33
34 25
    public function getSpaceId()
35
    {
36 25
        return $this->spaceId;
37
    }
38
39 25
    public function getManager()
40
    {
41 25
        return $this->manager;
42
    }
43
44 25
    public function getName()
45
    {
46 25
        return $this->name;
47
    }
48
49 25
    public function addIndex($properties, array $arguments = null)
50
    {
51 25
        $properties = (array) $properties;
52 25
        foreach ($properties as $property) {
53 25
            if (!$this->hasProperty($property)) {
54 1
                throw new LogicException("Unknown property $property for ".$this->name);
55
            }
56 25
        }
57
58 25
        $schema = $this->manager->getSchema();
59
60 25
        sort($properties);
61 25
        $indexName = implode('_', $properties);
62
63 25
        if ($schema->hasIndex($this->getName(), $indexName)) {
64 1
            throw new LogicException("Index $indexName already exists!");
65
        }
66 25
        if (!$arguments) {
67 25
            $arguments = [];
68 25
        }
69
70 25
        if (!array_key_exists('parts', $arguments) || !count($arguments['parts'])) {
71 25
            $arguments['parts'] = [];
72 25
            foreach($properties as $name) {
73 25
                $index = array_search($name, $this->properties);
74 25
                $arguments['parts'][] = $index + 1;
75 25
                $arguments['parts'][] = $this->convention->getTarantoolType($this->types[$name]);
76 25
            }
77 25
        }
78
79 25
        $schema->createIndex($this->getName(), $indexName, $arguments);
80
81 25
        return $this;
82
    }
83
84
    /**
85
     * @param $property name
86
     *
87
     * @return Type
88
     */
89 25
    public function addProperty($first)
90
    {
91 25
        $properties = is_array($first) ? $first : func_get_args();
92
93 25
        foreach ($properties as $name) {
94 25
            if ($this->hasProperty($name)) {
95 1
                throw new LogicException("Duplicate property $name");
96 1
            }
97 25
            $this->types[$name] = $this->manager->getMeta()->getConvention()->getType($name);
98 25
            $this->manager->create('property', [
99 25
                'space' => $this->spaceId,
100 25
                'index' => count($this->properties),
101 25
                'name' => $name,
102 25
                'type' => $this->types[$name],
103 25
            ]);
104
105 25
            $this->properties[] = $name;
106 25
        }
107
108 25
        return $this;
109
    }
110
111 25
    public function hasProperty($name)
112
    {
113 25
        return in_array($name, $this->properties);
114
    }
115
116 25
    public function getProperties()
117
    {
118 25
        return $this->properties;
119
    }
120
121 1
    public function getPropertyType($property)
122
    {
123 1
        return $this->types[$property];
124
    }
125
126 3
    public function setPropertyType($property, $type)
127
    {
128 3
        $this->types[$property] = $type;
129
130
        // update entity
131 3
        $row = $this->getManager()->get('property')->findOne([
0 ignored issues
show
Bug introduced by
The method findOne does only exist in Tarantool\Mapper\Contracts\Repository, but not in Tarantool\Mapper\Contracts\Entity.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
132 3
            'space' => $this->spaceId,
133 3
            'index' => array_search($property, $this->properties),
134 3
        ]);
135 3
        $row->type = $type;
136 3
        $this->getManager()->save($row);
137
138 3
        return $this;
139
    }
140
141 3
    public function reference(Contracts\Type $foreign, $property = null)
142
    {
143 3
        if (!$property) {
144 2
            $property = $foreign->getName();
145 2
        }
146
147 3
        $this->addProperty($property);
148 3
        $this->setPropertyType($property, $foreign->getName());
149 3
        $this->addIndex($property, ['unique' => false]);
150
151 3
        return $this;
152
    }
153
154 25
    public function isReference($property)
155
    {
156 25
        return !$this->convention->isPrimitive($this->types[$property]);
157
    }
158
159 3
    public function getReferenceProperty(Contracts\Type $type)
160
    {
161 3
        $properties = [];
162 3
        foreach ($this->types as $property => $propertyType) {
163 3
            if ($type->getName() == $propertyType) {
164 2
                $properties[] = $property;
165 2
            }
166 3
        }
167 3
        if (!count($properties)) {
168 1
            throw new LogicException('Type '.$this->getName().' is not related with '.$type->getName());
169
        }
170 2
        if (count($properties) > 1) {
171 1
            throw new LogicException('Multiple type reference found');
172
        }
173
174 1
        return $properties[0];
175
    }
176
177 1
    public function getReferences()
178
    {
179 1
        $references = [];
180 1
        $convention = $this->manager->getMeta()->getConvention();
181 1
        foreach ($this->types as $property => $type) {
182 1
            if (!$convention->isPrimitive($type)) {
183 1
                $references[$property] = $type;
184 1
            }
185 1
        }
186
187 1
        return $references;
188
    }
189
190 25
    public function getRequiredProperties()
191
    {
192 25
        if (!isset($this->requiredProperties)) {
193 25
            $this->requiredProperties = ['id' => 1];
0 ignored issues
show
Bug introduced by
The property requiredProperties does not seem to exist. Did you mean properties?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
194 25
            $indexList = $this->manager->getSchema()->listIndexes($this->getName());
195 25
            foreach ($indexList as $name => $fields) {
196 25
                foreach ($fields as $num) {
197 25
                    $this->requiredProperties[$this->properties[$num]] = true;
0 ignored issues
show
Bug introduced by
The property requiredProperties does not seem to exist. Did you mean properties?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
198 25
                }
199 25
            }
200 25
            $this->requiredProperties = array_keys($this->requiredProperties);
0 ignored issues
show
Bug introduced by
The property requiredProperties does not seem to exist. Did you mean properties?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
201 25
        }
202
203 25
        return $this->requiredProperties;
0 ignored issues
show
Bug introduced by
The property requiredProperties does not seem to exist. Did you mean properties?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
204
    }
205
206 25 View Code Duplication
    public function encode($input)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
207
    {
208 25
        $output = [];
209 25
        foreach ($this->getProperties() as $index => $name) {
210 25
            if (array_key_exists($name, $input)) {
211 25
                $output[$index] = $this->convention->encode($this->types[$name], $input[$name]);
212 25
            }
213 25
        }
214
215 25
        return $output;
216
    }
217
218 25 View Code Duplication
    public function decode($input)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
219
    {
220 25
        $output = [];
221 25
        foreach ($this->getProperties() as $index => $name) {
222 25
            if (array_key_exists($index, $input)) {
223 25
                $output[$name] = $this->convention->decode($this->types[$name], $input[$index]);
224 25
            }
225 25
        }
226
227 25
        return $output;
228
    }
229
}
230