Completed
Push — master ( a5b86a...23223e )
by Ducatel
03:40
created

AbstractTypedCollection::checkEquality()   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 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 2
crap 1
1
<?php
2
3
namespace Ducatel\PHPCollection\Base;
4
5
abstract class AbstractTypedCollection extends AbstractCollection
6
{
7
    /**
8
     * @var \Closure The function used to check if an object is belongs to the type of this collection
9
     * This function must take one argument and return true when args is in valid type (false otherwise)
10
     */
11
    private $validateTypeFct;
12
13
    /**
14
     * @var \Closure The function used to check if two object are equals
15
     * This function must take two arguments and return true when arguments are equals (false otherwise)
16
     */
17
    private $equalsFct;
18
19
    /**
20
     * AbstractTypedCollection constructor.
21
     *
22
     * @param string|\Closure $type Two value are possible for this field.
23
     *  1. The class name of object you want to store in this collection
24
     *  2. A function which take one arguments and return true when it in the good type (false otherwise)
25
     * @param null|\Closure $equalsFct When you pass null, the object will use the function \Equatable::equals if exist, else use the ===
26
     *                                 When you pass a Closure, the function must take two arguments and return true when 2 arguments are equals
27
     */
28 10
    public function __construct($type, $equalsFct = null)
29
    {
30 10
        if (is_callable($type)) {
31 8
            $this->validateTypeFct = $type;
0 ignored issues
show
Documentation Bug introduced by
It seems like $type can also be of type string. However, the property $validateTypeFct is declared as type object<Closure>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
32
        } else {
33
            $this->validateTypeFct = function ($object) use ($type) {
34 2
                return ($object instanceof $type);
35
            };
36
        }
37
38 10
        if ($equalsFct === null) {
39 5
            if (is_callable($type)) {
40
                $this->equalsFct = function ($obj1, $obj2) {
41 3
                    return $obj1 === $obj2;
42 3
                };
43
            } else {
44 5
                $this->equalsFct = function ($obj1, $obj2) {
45
                    return $obj1->equals($obj2);
46 5
                };
47
            }
48
        } else {
49 5
            $this->equalsFct = $equalsFct;
50
        }
51 10
    }
52
53
    /**
54
     * Check if an object can be manage by the current collection
55
     * @param $object The object you want to test
56
     * @return bool True if can be added false otherwise
57
     */
58 10
    public function validateType($object) : bool
59
    {
60 10
        return (call_user_func($this->validateTypeFct, $object) === true);
61
    }
62
63
    /**
64
     * Check if two object are equals
65
     * @param $object1 First object you want to compare to
66
     * @param $object2 Second object you want to compare
67
     * @return bool True if objects are equals false otherwise
68
     */
69 8
    private function checkEquality($object1, $object2) : bool
70
    {
71 8
        return (call_user_func($this->equalsFct, $object1, $object2) === true);
72
    }
73
74
    /**
75
     * Check if an object is present in the collection.
76
     * The check will be done by `Equatable::equals()` method if exist else use `===`
77
     *
78
     * @param $objectToFind The object you want to check if it's already present.
79
     *
80
     * @return bool True if present else false
81
     * @throws \TypeError When object in parameter is not good
82
     */
83 8
    public function contains($objectToFind) : bool
84
    {
85 8
        if ($this->validateType($objectToFind) === false) {
86 4
            throw new \TypeError("Object in parameter is not an instance of a good class");
0 ignored issues
show
Unused Code introduced by
The call to TypeError::__construct() has too many arguments starting with 'Object in parameter is ...stance of a good class'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
87
        }
88
89 8
        foreach ($this as $elem) {
90 8
            if ($this->checkEquality($elem, $objectToFind)) {
91 8
                return true;
92
            }
93
        }
94 6
        return false;
95
    }
96
}
97