Completed
Push — master ( 9108f3...77cd73 )
by Alex
03:46
created

Parser::isItem()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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