Completed
Pull Request — master (#16)
by Matthijs
12:11
created

DiscovererSet::filter()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 11
rs 9.2
cc 4
eloc 6
nc 4
nop 1
1
<?php
2
3
namespace VDB\Spider\Discoverer;
4
5
use VDB\Spider\Resource;
6
use VDB\Spider\Filter\PreFetchFilter;
7
use VDB\Spider\Uri\FilterableUri;
8
9
class DiscovererSet implements \IteratorAggregate {
10
11
    /**
12
     * @var Discoverer[]
13
     */
14
    private $discoverers = array();
15
16
    /** @var Filter[] */
17
    private $filters = array();
18
19
    public function __construct(array $discoverers = array())
20
    {
21
        foreach ($discoverers as $alias => $discoverer) {
22
            $this->set($discoverer, is_int($alias) ? null : $alias);
23
        }
24
    }
25
26
    /**
27
     * @param Resource $resource
28
     * @return UriInterface[]
29
     */
30
    public function discover(Resource $resource)
31
    {
32
        $discoveredUris = array();
33
34
        foreach ($this->discoverers as $discoverer) {
35
            $discoveredUris = array_merge($discoveredUris, $discoverer->discover($resource));
36
        }
37
38
        // TODO: perf improvement: do al this in one loop instead of three
39
        $this->normalize($discoveredUris);
40
        $this->removeDuplicates($discoveredUris);
41
        $this->filter($discoveredUris);
42
43
        return $discoveredUris;
44
    }
45
46
    /**
47
     * Sets a discoverer.
48
     *
49
     * @param discovererInterface $discoverer The discoverer instance
50
     * @param string          $alias  An alias
51
     */
52
    public function set(DiscovererInterface $discoverer, $alias = null)
53
    {
54
        $this->discoverers[$discoverer->getName()] = $discoverer;
55
        if (null !== $alias) {
56
            $this->discoverers[$alias] = $discoverer;
57
        }
58
59
        $discoverer->setDiscovererSet($this);
60
    }
61
62
    /**
63
     * @param Filter $filter
64
     */
65
    public function addFilter(PreFetchFilter $filter)
66
    {
67
        $this->filters[] = $filter;
68
    }
69
70
    /**
71
     * Returns true if the discoverer is defined.
72
     *
73
     * @param string $name The discoverer name
74
     *
75
     * @return bool true if the discoverer is defined, false otherwise
76
     */
77
    public function has($name)
78
    {
79
        return isset($this->discoverers[$name]);
80
    }
81
82
    /**
83
     * Gets a discoverer.
84
     *
85
     * @param string $name The discoverer name
86
     *
87
     * @return Discoverer The discoverer instance
88
     *
89
     * @throws InvalidArgumentException if the discoverer is not defined
90
     */
91
    public function get($name)
92
    {
93
        if (!$this->has($name)) {
94
            throw new \InvalidArgumentException(sprintf('The discoverer "%s" is not defined.', $name));
95
        }
96
97
        return $this->discoverers[$name];
98
    }
99
100
    public function getIterator()
101
    {
102
        return new \ArrayIterator($this->helpers);
0 ignored issues
show
Bug introduced by
The property helpers does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
103
    }
104
105
    /**
106
     * @param UriInterface[] $discoveredUris
107
     */
108
    private function normalize(array &$discoveredUris)
109
    {
110
        foreach ($discoveredUris as &$uri) {
111
            $uri->normalize();
112
        }
113
    }
114
115
    /**
116
     * @param UriInterface[] $discoveredUris
117
     */
118
    private function filter(array &$discoveredUris)
119
    {
120
        foreach ($discoveredUris as $k => &$uri) {
121
            $uri = new FilterableUri($uri->toString());
122
            foreach ($this->filters as $filter) {
123
                if ($filter->match($uri)) {
124
                    unset($discoveredUris[$k]);
125
                }
126
            }
127
        }
128
    }
129
130
    /**
131
     * @param UriInterface[] $discoveredUris
132
     */
133
    private function removeDuplicates(array &$discoveredUris)
134
    {
135
        // make sure there are no duplicates in the list
136
        $tmp = array();
137
        /** @var Uri $uri */
138
        foreach ($discoveredUris as $k => $uri) {
139
            $tmp[$k] = $uri->toString();
140
        }
141
142
        // Find duplicates in temporary array
143
        $tmp = array_unique($tmp);
144
145
        // Remove the duplicates from original array
146
        foreach ($discoveredUris as $k => $uri) {
147
            if (!array_key_exists($k, $tmp)) {
148
                unset($discoveredUris[$k]);
149
            }
150
        }
151
    }
152
}
153