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

DiscovererSet::set()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 9
rs 9.6667
cc 2
eloc 5
nc 2
nop 2
1
<?php
2
3
namespace VDB\Spider\Discoverer;
4
5
use VDB\Spider\Resource;
6
use VDB\Spider\Filter\PreFetchFilterInterface;
7
use VDB\Spider\Uri\FilterableUri;
8
9
class DiscovererSet implements \IteratorAggregate
10
{
11
12
    /**
13
     * @var Discoverer[]
14
     */
15
    private $discoverers = array();
16
17
    /** @var Filter[] */
18
    private $filters = array();
19
20
    public function __construct(array $discoverers = array())
21
    {
22
        foreach ($discoverers as $alias => $discoverer) {
23
            $this->set($discoverer, is_int($alias) ? null : $alias);
24
        }
25
    }
26
27
    /**
28
     * @param Resource $resource
29
     * @return UriInterface[]
30
     */
31
    public function discover(Resource $resource)
32
    {
33
        $discoveredUris = array();
34
35
        foreach ($this->discoverers as $discoverer) {
36
            $discoveredUris = array_merge($discoveredUris, $discoverer->discover($resource));
37
        }
38
39
        // TODO: perf improvement: do al this in one loop instead of three
40
        $this->normalize($discoveredUris);
41
        $this->removeDuplicates($discoveredUris);
42
        $this->filter($discoveredUris);
43
44
        return $discoveredUris;
45
    }
46
47
    /**
48
     * Sets a discoverer.
49
     *
50
     * @param discovererInterface $discoverer The discoverer instance
51
     * @param string          $alias  An alias
0 ignored issues
show
Documentation introduced by
Should the type for parameter $alias not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
52
     */
53
    public function set(DiscovererInterface $discoverer, $alias = null)
54
    {
55
        $this->discoverers[$discoverer->getName()] = $discoverer;
56
        if (null !== $alias) {
57
            $this->discoverers[$alias] = $discoverer;
58
        }
59
60
        $discoverer->setDiscovererSet($this);
61
    }
62
63
    /**
64
     * @param PreFetchFilterInterface $filter
65
     */
66
    public function addFilter(PreFetchFilterInterface $filter)
67
    {
68
        $this->filters[] = $filter;
69
    }
70
71
    /**
72
     * Returns true if the discoverer is defined.
73
     *
74
     * @param string $name The discoverer name
75
     *
76
     * @return bool true if the discoverer is defined, false otherwise
77
     */
78
    public function has($name)
79
    {
80
        return isset($this->discoverers[$name]);
81
    }
82
83
    /**
84
     * Gets a discoverer.
85
     *
86
     * @param string $name The discoverer name
87
     *
88
     * @return Discoverer The discoverer instance
89
     *
90
     * @throws InvalidArgumentException if the discoverer is not defined
91
     */
92
    public function get($name)
93
    {
94
        if (!$this->has($name)) {
95
            throw new \InvalidArgumentException(sprintf('The discoverer "%s" is not defined.', $name));
96
        }
97
98
        return $this->discoverers[$name];
99
    }
100
101
    public function getIterator()
102
    {
103
        return new \ArrayIterator($this->discoverers);
104
    }
105
106
    /**
107
     * @param UriInterface[] $discoveredUris
108
     */
109
    private function normalize(array &$discoveredUris)
110
    {
111
        foreach ($discoveredUris as &$uri) {
112
            $uri->normalize();
113
        }
114
    }
115
116
    /**
117
     * @param UriInterface[] $discoveredUris
118
     */
119
    private function filter(array &$discoveredUris)
120
    {
121
        foreach ($discoveredUris as $k => &$uri) {
122
            $uri = new FilterableUri($uri->toString());
123
            foreach ($this->filters as $filter) {
124
                if ($filter->match($uri)) {
125
                    unset($discoveredUris[$k]);
126
                }
127
            }
128
        }
129
    }
130
131
    /**
132
     * @param UriInterface[] $discoveredUris
133
     */
134
    private function removeDuplicates(array &$discoveredUris)
135
    {
136
        // make sure there are no duplicates in the list
137
        $tmp = array();
138
        /** @var Uri $uri */
139
        foreach ($discoveredUris as $k => $uri) {
140
            $tmp[$k] = $uri->toString();
141
        }
142
143
        // Find duplicates in temporary array
144
        $tmp = array_unique($tmp);
145
146
        // Remove the duplicates from original array
147
        foreach ($discoveredUris as $k => $uri) {
148
            if (!array_key_exists($k, $tmp)) {
149
                unset($discoveredUris[$k]);
150
            }
151
        }
152
    }
153
}
154