MultipleOfConstraint::normalize()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 8
cts 8
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 7
nc 3
nop 3
crap 3
1
<?php
2
3
/*
4
 * This file is part of the JVal package.
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace JVal\Constraint;
11
12
use JVal\Constraint;
13
use JVal\Context;
14
use JVal\Exception\Constraint\InvalidTypeException;
15
use JVal\Exception\Constraint\NotStrictlyPositiveException;
16
use JVal\Types;
17
use JVal\Walker;
18
use stdClass;
19
20
/**
21
 * Constraint for the "multipleOf" keyword.
22
 */
23
class MultipleOfConstraint implements Constraint
24
{
25
    /**
26
     * {@inheritdoc}
27
     */
28 373
    public function keywords()
29
    {
30 373
        return ['multipleOf'];
31
    }
32
33
    /**
34
     * {@inheritdoc}
35
     */
36 357
    public function supports($type)
37
    {
38 357
        return $type === Types::TYPE_INTEGER || $type === Types::TYPE_NUMBER;
39
    }
40
41
    /**
42
     * {@inheritdoc}
43
     */
44 22
    public function normalize(stdClass $schema, Context $context, Walker $walker)
45
    {
46 22
        $context->enterNode('multipleOf');
47
48 22
        if (!Types::isA($schema->multipleOf, Types::TYPE_NUMBER)) {
49 1
            throw new InvalidTypeException($context, Types::TYPE_NUMBER);
50
        }
51
52 21
        if ($schema->multipleOf <= 0) {
53 2
            throw new NotStrictlyPositiveException($context);
54
        }
55
56 19
        $context->leaveNode();
57 19
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62 18
    public function apply($instance, stdClass $schema, Context $context, Walker $walker)
63
    {
64 18
        $divider = $schema->multipleOf;
65 18
        $modulus = fmod($instance, $divider);
66 18
        $precision = abs(0.0000000001);
67 18
        $diff = (float) ($modulus - $divider);
68
69 18
        if (-$precision < $diff && $diff < $precision) {
70 1
            $fMod = 0.0;
71 1
        } else {
72 17
            $decimals1 = mb_strpos($instance, '.') ?
73 17
                mb_strlen($instance) - mb_strpos($instance, '.') - 1 :
74 17
                0;
75 17
            $decimals2 = mb_strpos($divider, '.') ?
76 17
                mb_strlen($divider) - mb_strpos($divider, '.') - 1 :
77 17
                0;
78 17
            $fMod = (float) round($modulus, max($decimals1, $decimals2));
79
        }
80
81 18
        if ($fMod != 0) {
82 6
            $context->addViolation('should be a multiple of %s', [$divider]);
83 6
        }
84 18
    }
85
}
86