Completed
Push — issue/70 ( 39b47c )
by Alex
03:11
created

Parser::resetFilters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
crap 1
1
<?php
2
/*
3
 * This file is part of the feed-io package.
4
 *
5
 * (c) Alexandre Debril <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace FeedIo;
12
13
use DOMDocument;
14
use FeedIo\Feed\ItemInterface;
15
use FeedIo\Feed\NodeInterface;
16
use FeedIo\Parser\MissingFieldsException;
17
use FeedIo\Parser\UnsupportedFormatException;
18
use Psr\Log\LoggerInterface;
19
20
/**
21
 * Parses a DOM document if its format matches the parser's standard
22
 *
23
 * Depends on :
24
 *  - FeedIo\StandardAbstract
25
 *  - Psr\Log\LoggerInterface
26
 *
27
 */
28
class Parser
29
{
30
31
    /**
32
     * @var \Psr\Log\LoggerInterface
33
     */
34
    protected $logger;
35
36
    /**
37
     * @var array[FilterInterface]
38
     */
39
    protected $filters = array();
40
41
    /**
42
     * @var StandardAbstract
43
     */
44
    protected $standard;
45
46
    /**
47
     * @param StandardAbstract $standard
48
     * @param LoggerInterface  $logger
49
     */
50 33
    public function __construct(StandardAbstract $standard, LoggerInterface $logger)
51
    {
52 33
        $this->standard = $standard;
53 33
        $this->logger = $logger;
54 33
    }
55
56
    /**
57
     * @return StandardAbstract
58
     */
59 20
    public function getStandard()
60
    {
61 20
        return $this->standard;
62
    }
63
64
    /**
65
     * @param $tagName
66
     * @return bool
67
     */
68 7
    public function isItem($tagName)
69
    {
70 7
        return (strtolower($this->standard->getItemNodeName()) === strtolower($tagName));
71
    }
72
73
    /**
74
     * @param  FilterInterface $filter
75
     * @return $this
76
     */
77 4
    public function addFilter(FilterInterface $filter)
78
    {
79 4
        $this->filters[] = $filter;
80
81 4
        return $this;
82
    }
83
84
    /**
85
     * Reset filters
86
     * @return $this
87
     */
88 1
    public function resetFilters()
89
    {
90 1
        $this->filters = [];
91
92 1
        return $this;
93
    }
94
95
    /**
96
     * @param  DOMDocument                       $document
97
     * @param  FeedInterface                     $feed
98
     * @return \FeedIo\FeedInterface
99
     * @throws Parser\MissingFieldsException
100
     * @throws Parser\UnsupportedFormatException
101
     */
102 8
    public function parse(DOMDocument $document, FeedInterface $feed)
103
    {
104 8
        if (!$this->standard->canHandle($document)) {
105 1
            throw new UnsupportedFormatException('this is not a supported format');
106
        }
107
108 7
        $this->checkBodyStructure($document, $this->standard->getMandatoryFields());
109 7
        $element = $this->standard->getMainElement($document);
110
111 7
        $this->parseNode($feed, $element, $this->standard->getFeedRuleSet());
112
113 7
        return $feed;
114
    }
115
116
    /**
117
     * @param  DOMDocument            $document
118
     * @param  array                  $mandatoryFields
119
     * @return $this
120
     * @throws MissingFieldsException
121
     */
122 9
    public function checkBodyStructure(DOMDocument $document, array $mandatoryFields)
123
    {
124 9
        $errors = array();
125
126 9
        $element = $document->documentElement;
127 9
        foreach ($mandatoryFields as $field) {
128 2
            $list = $element->getElementsByTagName($field);
129 2
            if (0 === $list->length) {
130 1
                $errors[] = $field;
131 1
            }
132 9
        }
133
134 9
        if (!empty($errors)) {
135 1
            $message = "missing mandatory field(s) : ".implode(',', $errors);
136 1
            $this->logger->warning($message);
137 1
            throw new MissingFieldsException($message);
138
        }
139
140 8
        return $this;
141
    }
142
143
    /**
144
     * @param  NodeInterface $item
145
     * @param  \DOMElement   $element
146
     * @param  RuleSet       $ruleSet
147
     * @return NodeInterface
148
     */
149 8
    public function parseNode(NodeInterface $item, \DOMElement $element, RuleSet $ruleSet)
150
    {
151 8
        foreach ($element->childNodes as $node) {
152 7
            if ($node instanceof \DOMElement) {
153 7
                $this->handleNode($item, $node, $ruleSet);
154 7
            }
155 8
        }
156
157 8
        return $item;
158
    }
159
160
    /**
161
     * @param NodeInterface $item
162
     * @param \DOMElement $node
163
     * @param RuleSet $ruleSet
164
     * @return $this
165
     */
166 7
    protected function handleNode(NodeInterface $item, \DOMElement $node, RuleSet $ruleSet)
167
    {
168 7
        if ($this->isItem($node->tagName) && $item instanceof FeedInterface) {
169 6
            $newItem = $this->parseNode($item->newItem(), $node, $this->standard->getItemRuleSet());
170 6
            $this->addValidItem($item, $newItem);
171 6
        } else {
172 7
            $rule = $ruleSet->get($node->tagName);
173 7
            $rule->setProperty($item, $node);
174
        }
175
176 7
        return $this;
177
    }
178
179
    /**
180
     * @param  FeedInterface $feed
181
     * @param  NodeInterface $item
182
     * @return $this
183
     */
184 6
    public function addValidItem(FeedInterface $feed, NodeInterface $item)
185
    {
186 6
        if ($item instanceof ItemInterface && $this->isValid($item)) {
187 6
            $feed->add($item);
188 6
        }
189
190 6
        return $this;
191
    }
192
193
    /**
194
     * @param  ItemInterface $item
195
     * @return bool
196
     */
197 8
    public function isValid(ItemInterface $item)
198
    {
199 8
        foreach ($this->filters as $filter) {
200 2
            if (!$filter->isValid($item)) {
201 1
                return false;
202
            }
203 7
        }
204
205 7
        return true;
206
    }
207
}
208