Completed
Push — master ( abe227...316baf )
by Raffael
13:55 queued 08:01
created

Schema::getType()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.4746

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 5
cts 8
cp 0.625
rs 9.568
c 0
b 0
f 0
cc 3
nc 3
nop 1
crap 3.4746
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * tubee.io
7
 *
8
 * @copyright   Copryright (c) 2017-2019 gyselroth GmbH (https://gyselroth.com)
9
 * @license     GPL-3.0 https://opensource.org/licenses/GPL-3.0
10
 */
11
12
namespace Tubee;
13
14
use MongoDB\BSON\Binary;
15
use Psr\Log\LoggerInterface;
16
use Tubee\AttributeMap\AttributeMapInterface;
17
use Tubee\Schema\Exception;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Tubee\Exception.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
18
use Tubee\Schema\SchemaInterface;
19
20
class Schema implements SchemaInterface
21
{
22
    /**
23
     * Attribute schema.
24
     *
25
     * @var iterable
26
     */
27
    protected $schema = [];
28
29
    /**
30
     * Logger.
31
     *
32
     * @var LoggerInterface
33
     */
34
    protected $logger;
35
36
    /**
37
     * Init attribute schema.
38
     */
39 11
    public function __construct(array $schema, LoggerInterface $logger)
40
    {
41 11
        $this->schema = $schema;
0 ignored issues
show
Documentation Bug introduced by
It seems like $schema of type array is incompatible with the declared type object<Tubee\iterable> of property $schema.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
42 11
        $this->logger = $logger;
43 11
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48
    public function getSchema(): array
49
    {
50
        return $this->schema;
51
    }
52
53
    /**
54
     * {@inheritdoc}
55
     */
56
    public function getAttributes(): array
57
    {
58
        return array_keys($this->schema);
59
    }
60
61
    /**
62
     * {@inheritdoc}
63
     */
64 6
    public function validate(array $data): bool
65
    {
66 6
        foreach ($this->schema as $attribute => $value) {
67 6
            if (isset($value['required']) && $value['required'] === true && !isset($data[$attribute])) {
68 1
                throw new Exception\AttributeNotFound('attribute '.$attribute.' is required');
69
            }
70
71 5
            if (!isset($data[$attribute])) {
72
                continue;
73
            }
74
75 5
            if (isset($value['type']) && $this->getType($data[$attribute]) !== $value['type']) {
76 1
                throw new Exception\AttributeInvalidType('attribute '.$attribute.' value is not of type '.$value['type']);
77
            }
78
79 4
            if (isset($value['require_regex'])) {
80 2
                $this->requireRegex($data[$attribute], $attribute, $value['require_regex']);
81
            }
82
83 3
            $this->logger->debug('schema attribute ['.$attribute.'] with value [{value}] is valid', [
84 3
                'category' => get_class($this),
85 3
                'value' => $data[$attribute],
86
            ]);
87
        }
88
89 3
        return true;
90
    }
91
92
    /**
93
     * Get type.
94
     */
95 2
    protected function getType($value): ?string
96
    {
97
        $map = [
98 2
            'string' => AttributeMapInterface::TYPE_STRING,
99
            'array' => AttributeMapInterface::TYPE_ARRAY,
100
            'integer' => AttributeMapInterface::TYPE_INT,
101
            'double' => AttributeMapInterface::TYPE_FLOAT,
102
            'boolean' => AttributeMapInterface::TYPE_BOOL,
103
            'null' => AttributeMapInterface::TYPE_NULL,
104
        ];
105
106 2
        $type = gettype($value);
107
108 2
        if (isset($map[$type])) {
109 2
            return $map[$type];
110
        }
111
        if ($value instanceof Binary) {
0 ignored issues
show
Bug introduced by
The class MongoDB\BSON\Binary does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
112
            return AttributeMapInterface::TYPE_BINARY;
113
        }
114
115
        return null;
116
    }
117
118
    /**
119
     * Require regex value.
120
     */
121 2
    protected function requireRegex($value, string $attribute, string $regex): bool
122
    {
123 2
        if (is_iterable($value)) {
124
            foreach ($value as $value_child) {
125
                if (!preg_match($regex, $value_child)) {
126
                    throw new Exception\AttributeRegexNotMatch('resolve attribute '.$attribute.' value does not match require_regex');
127
                }
128
            }
129
        } else {
130 2
            if (!preg_match($regex, $value)) {
131 1
                throw new Exception\AttributeRegexNotMatch('resolve attribute '.$attribute.' value does not match require_regex');
132
            }
133
        }
134
135 1
        return true;
136
    }
137
}
138