AbstractTypedCollection::contains()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 7
cts 7
cp 1
rs 9.2
c 0
b 0
f 0
cc 4
eloc 7
nc 4
nop 1
crap 4
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
     * @throws \TypeError When parameter are not in a valid type
28
     */
29 14
    public function __construct($type, $equalsFct = null)
30
    {
31 14
        if ($this->is_closure($type) === false && is_string($type) === false) {
32 1
            throw new \TypeError('Parameter $type can be an object (string or instance) or a function');
0 ignored issues
show
Unused Code introduced by
The call to TypeError::__construct() has too many arguments starting with 'Parameter $type can be ...nstance) or a function'.

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...
33
        }
34
35 13
        if ($equalsFct !== null && $this->is_closure($equalsFct) === false) {
36 1
            throw new \TypeError('Parameter $equalsFct can be null or a function');
0 ignored issues
show
Unused Code introduced by
The call to TypeError::__construct() has too many arguments starting with 'Parameter $equalsFct can be null or a function'.

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...
37
        }
38
39 12
        if (is_string($type)) { // Collection of object
40
41
            $this->validateTypeFct = function ($object) use ($type) {
42 2
                return ($object instanceof $type);
43
            };
44
45 2
            if ($equalsFct === null) {
46 2
                $arrayOfInterface = class_implements($type);
47 2
                if (in_array("Ducatel\\PHPCollection\\Base\\Equatable", $arrayOfInterface)) {
48
                    $this->equalsFct = function ($obj1, $obj2) {
49
                        return $obj1->equals($obj2);
50 1
                    };
51
                } else {
52
                    $this->equalsFct = function ($obj1, $obj2) {
53
                        return $obj1 === $obj2;
54 2
                    };
55
                }
56
            } else {
57 2
                $this->equalsFct = $equalsFct;
58
            }
59
        } else {
60 10
            $this->validateTypeFct = $type;
61
62 10
            if ($equalsFct === null) {
63 5
                $this->equalsFct = function ($obj1, $obj2) {
64 5
                    return $obj1 === $obj2;
65 5
                };
66
            } else {
67 5
                $this->equalsFct = $equalsFct;
68
            }
69
        }
70 12
    }
71
72
    /**
73
     * Check if an object can be manage by the current collection
74
     * @param $object The object you want to test
75
     * @return bool True if can be added false otherwise
76
     */
77 12
    public function validateType($object) : bool
78
    {
79 12
        return (call_user_func($this->validateTypeFct, $object) === true);
80
    }
81
82
    /**
83
     * Check if two object are equals
84
     * @param $object1 First object you want to compare to
85
     * @param $object2 Second object you want to compare
86
     * @return bool True if objects are equals false otherwise
87
     */
88 10
    private function checkEquality($object1, $object2) : bool
89
    {
90 10
        return (call_user_func($this->equalsFct, $object1, $object2) === true);
91
    }
92
93
    /**
94
     * Check if the object in param is a Closure
95
     * @param $object The object you want to test
96
     * @return bool True if it's a valid closure, else false
97
     */
98 14
    protected function is_closure($object) : bool
99
    {
100 14
        return is_object($object) && ($object instanceof \Closure);
101
    }
102
103
    /**
104
     * Check if an object is present in the collection.
105
     * The check will be done by `Equatable::equals()` method if exist else use `===`
106
     *
107
     * @param $objectToFind The object you want to check if it's already present.
108
     *
109
     * @return bool True if present else false
110
     * @throws \TypeError When object in parameter is not good
111
     */
112 10
    public function contains($objectToFind) : bool
113
    {
114 10
        if ($this->validateType($objectToFind) === false) {
115 5
            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...
116
        }
117
118 10
        foreach ($this as $elem) {
119 10
            if ($this->checkEquality($elem, $objectToFind)) {
120 10
                return true;
121
            }
122
        }
123 8
        return false;
124
    }
125
}
126