Integer::__construct()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 10
ccs 6
cts 6
cp 1
rs 9.4285
c 1
b 0
f 0
cc 2
eloc 5
nc 2
nop 1
crap 2
1
<?php
2
3
namespace ValueObjects\Number;
4
5
use ValueObjects\Exception\InvalidNativeArgumentException;
6
use ValueObjects\Util\Util;
7
use ValueObjects\ValueObjectInterface;
8
9
class Integer extends Real
10
{
11
    /**
12
     * Returns a Integer object given a PHP native int as parameter.
13
     *
14
     * @param int $value
15
     */
16 104
    public function __construct($value)
17
    {
18 104
        $filteredValue = filter_var($value, FILTER_VALIDATE_INT);
19
20 104
        if (false === $filteredValue) {
21 1
            throw new InvalidNativeArgumentException($value, array('int'));
22
        }
23
24 103
        parent::__construct($filteredValue);
25 103
    }
26
27
    /**
28
     * Tells whether two Integer are equal by comparing their values
29
     *
30
     * @param  ValueObjectInterface $integer
31
     * @return bool
32
     */
33 46
    public function sameValueAs(ValueObjectInterface $integer)
34
    {
35 46
        if (false === Util::classEquals($this, $integer)) {
36 4
            return false;
37
        }
38
39 45
        return $this->toNative() === $integer->toNative();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface ValueObjects\ValueObjectInterface as the method toNative() does only exist in the following implementations of said interface: ValueObjects\Boolean\BoolLiteral, ValueObjects\Boolean\BooleanString, ValueObjects\Climate\Celsius, ValueObjects\Climate\Fahrenheit, ValueObjects\Climate\Kelvin, ValueObjects\Climate\RelativeHumidity, ValueObjects\Climate\Temperature, ValueObjects\DateTime\Hour, ValueObjects\DateTime\Minute, ValueObjects\DateTime\Month, ValueObjects\DateTime\MonthDay, ValueObjects\DateTime\Second, ValueObjects\DateTime\WeekDay, ValueObjects\DateTime\Year, ValueObjects\Enum\Enum, ValueObjects\Geography\Continent, ValueObjects\Geography\CountryCode, ValueObjects\Geography\DistanceFormula, ValueObjects\Geography\DistanceUnit, ValueObjects\Geography\Ellipsoid, ValueObjects\Geography\Latitude, ValueObjects\Geography\Longitude, ValueObjects\Identity\Imei, ValueObjects\Identity\MacAddress, ValueObjects\Identity\UUID, ValueObjects\Money\CurrencyCode, ValueObjects\Number\Complex, ValueObjects\Number\Integer, ValueObjects\Number\Natural, ValueObjects\Number\Real, ValueObjects\Number\RoundingMode, ValueObjects\Person\Age, ValueObjects\Person\Gender, ValueObjects\StringLiteral\StringLiteral, ValueObjects\Web\Domain, ValueObjects\Web\EmailAddress, ValueObjects\Web\FragmentIdentifier, ValueObjects\Web\Hostname, ValueObjects\Web\IPAddress, ValueObjects\Web\IPAddressVersion, ValueObjects\Web\IPv4Address, ValueObjects\Web\IPv6Address, ValueObjects\Web\NullFragmentIdentifier, ValueObjects\Web\NullQueryString, ValueObjects\Web\Path, ValueObjects\Web\PortNumber, ValueObjects\Web\QueryString, ValueObjects\Web\SchemeName.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
40
    }
41
42
    /**
43
     * Returns the value of the integer number
44
     *
45
     * @return int
46
     */
47 83
    public function toNative()
48
    {
49 83
        $value = parent::toNative();
50
51 83
        return \intval($value);
52
    }
53
54
    /**
55
     * Returns a Real with the value of the Integer
56
     *
57
     * @return Real
58
     */
59 1
    public function toReal()
60
    {
61 1
        $value = $this->toNative();
62 1
        $real  = new Real($value);
63
64 1
        return $real;
65
    }
66
}
67