Completed
Pull Request — master (#61)
by Alex
16:52 queued 06:57
created

Parser::addFilter()   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
c 0
b 0
f 0
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
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 34
    public function __construct(StandardAbstract $standard, LoggerInterface $logger)
51
    {
52 34
        $this->standard = $standard;
53 34
        $this->logger = $logger;
54 34
    }
55
56
    /**
57
     * @return StandardAbstract
58
     */
59 21
    public function getStandard()
60
    {
61 21
        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 10
    public function addFilter(FilterInterface $filter)
78
    {
79 10
        $this->filters[] = $filter;
80
81 10
        return $this;
82
    }
83
84
    /**
85
     * @param  DOMDocument                       $document
86
     * @param  FeedInterface                     $feed
87 8
     * @return \FeedIo\FeedInterface
88
     * @throws Parser\MissingFieldsException
89 8
     * @throws Parser\UnsupportedFormatException
90 1
     */
91
    public function parse(DOMDocument $document, FeedInterface $feed)
92
    {
93 8
        if (!$this->standard->canHandle($document)) {
94
            throw new UnsupportedFormatException('this is not a supported format');
95
        }
96
97
        $this->checkBodyStructure($document, $this->standard->getMandatoryFields());
98
        $element = $this->standard->getMainElement($document);
99
100
        $this->parseNode($feed, $element, $this->standard->getFeedRuleSet());
101
102
        return $feed;
103 8
    }
104
105 8
    /**
106 1
     * @param  DOMDocument            $document
107
     * @param  array                  $mandatoryFields
108
     * @return $this
109 7
     * @throws MissingFieldsException
110 7
     */
111 7
    public function checkBodyStructure(DOMDocument $document, array $mandatoryFields)
112
    {
113 7
        $errors = array();
114
115 7
        $element = $document->documentElement;
116
        foreach ($mandatoryFields as $field) {
117
            $list = $element->getElementsByTagName($field);
118
            if (0 === $list->length) {
119
                $errors[] = $field;
120
            }
121
        }
122
123
        if (!empty($errors)) {
124 9
            $message = "missing mandatory field(s) : ".implode(',', $errors);
125
            $this->logger->warning($message);
126 9
            throw new MissingFieldsException($message);
127
        }
128 9
129 9
        return $this;
130 2
    }
131 2
132 2
    /**
133
     * @param  NodeInterface $item
134
     * @param  \DOMElement   $element
135
     * @param  RuleSet       $ruleSet
136 9
     * @return NodeInterface
137 1
     */
138 1
    public function parseNode(NodeInterface $item, \DOMElement $element, RuleSet $ruleSet)
139 1
    {
140
        foreach ($element->childNodes as $node) {
141
            if ($node instanceof \DOMElement) {
142 8
                $this->handleNode($item, $node, $ruleSet);
143
            }
144
        }
145
146
        return $item;
147
    }
148
149
    /**
150
     * @param NodeInterface $item
151 8
     * @param \DOMElement $node
152
     * @param RuleSet $ruleSet
153 8
     * @return $this
154 7
     */
155 7
    protected function handleNode(NodeInterface $item, \DOMElement $node, RuleSet $ruleSet)
156
    {
157
        if ($this->isItem($node->tagName) && $item instanceof FeedInterface) {
158
            $newItem = $this->parseNode($item->newItem(), $node, $this->standard->getItemRuleSet());
159 8
            $this->addValidItem($item, $newItem);
160
        } else {
161
            $rule = $ruleSet->get($node->tagName);
162
            $rule->setProperty($item, $node);
163
        }
164
165
        return $this;
166
    }
167
168 7
    /**
169
     * @param  FeedInterface $feed
170 7
     * @param  NodeInterface $item
171 6
     * @return $this
172 6
     */
173
    public function addValidItem(FeedInterface $feed, NodeInterface $item)
174 7
    {
175 7
        if ($item instanceof ItemInterface && $this->isValid($item)) {
176
            $feed->add($item);
177
        }
178 7
179
        return $this;
180
    }
181
182
    /**
183
     * @param  ItemInterface $item
184
     * @return bool
185
     */
186 6
    public function isValid(ItemInterface $item)
187
    {
188 6
        foreach ($this->filters as $filter) {
189 6
            if (!$filter->isValid($item)) {
190
                return false;
191
            }
192 6
        }
193
194
        return true;
195
    }
196
}
197