Completed
Push — master ( 9c755e...912090 )
by Joschi
02:56
created

RdfaLiteElementProcessor::processProperty()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4.5923

Importance

Changes 3
Bugs 0 Features 0
Metric Value
dl 0
loc 18
ccs 8
cts 12
cp 0.6667
rs 9.2
c 3
b 0
f 0
cc 4
eloc 12
nc 2
nop 2
crap 4.5923
1
<?php
2
3
/**
4
 * rdfa-lite-microdata
5
 *
6
 * @category Jkphl
7
 * @package Jkphl\RdfaLiteMicrodata
8
 * @subpackage Jkphl\RdfaLiteMicrodata\Infrastructure
9
 * @author Joschi Kuphal <[email protected]> / @jkphl
10
 * @copyright Copyright © 2017 Joschi Kuphal <[email protected]> / @jkphl
11
 * @license http://opensource.org/licenses/MIT The MIT License (MIT)
12
 */
13
14
/***********************************************************************************
15
 *  The MIT License (MIT)
16
 *
17
 *  Copyright © 2017 Joschi Kuphal <[email protected]> / @jkphl
18
 *
19
 *  Permission is hereby granted, free of charge, to any person obtaining a copy of
20
 *  this software and associated documentation files (the "Software"), to deal in
21
 *  the Software without restriction, including without limitation the rights to
22
 *  use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
23
 *  the Software, and to permit persons to whom the Software is furnished to do so,
24
 *  subject to the following conditions:
25
 *
26
 *  The above copyright notice and this permission notice shall be included in all
27
 *  copies or substantial portions of the Software.
28
 *
29
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
31
 *  FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
32
 *  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
33
 *  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34
 *  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
 ***********************************************************************************/
36
37
namespace Jkphl\RdfaLiteMicrodata\Infrastructure\Parser;
38
39
use Jkphl\RdfaLiteMicrodata\Application\Context\ContextInterface;
40
use Jkphl\RdfaLiteMicrodata\Application\Context\RdfaLiteContext;
41
use Jkphl\RdfaLiteMicrodata\Application\Parser\RootThing;
42
use Jkphl\RdfaLiteMicrodata\Domain\Thing\ThingInterface;
43
use Jkphl\RdfaLiteMicrodata\Domain\Vocabulary\Vocabulary;
44
use Jkphl\RdfaLiteMicrodata\Domain\Vocabulary\VocabularyInterface;
45
46
/**
47
 * RDFa Lite 1.1 element processor
48
 *
49
 * @package Jkphl\RdfaLiteMicrodata
50
 * @subpackage Jkphl\RdfaLiteMicrodata\Infrastructure
51
 */
52
class RdfaLiteElementProcessor extends AbstractElementProcessor
53
{
54
    /**
55
     * Process a DOM element
56
     *
57
     * @param \DOMElement $element DOM element
58
     * @param ContextInterface $context Inherited Context
59
     * @return ContextInterface Local context for this element
60
     */
61 13
    public function processElement(\DOMElement $element, ContextInterface $context)
62
    {
63
        // Process default vocabulary registrations
64 13
        $context = $this->processVocab($element, $context);
65
66
        // Register vocabulary prefixes
67 13
        $context = $this->processPrefix($element, $context);
68
69
        // Create a property
70 13
        return $this->processProperty($element, $context);
71
    }
72
73
    /**
74
     * Process changes of the default vocabulary
75
     *
76
     * @param \DOMElement $element DOM element
77
     * @param ContextInterface $context Inherited Context
78
     * @return ContextInterface Local context for this element
79
     */
80 13
    protected function processVocab(\DOMElement $element, ContextInterface $context)
81
    {
82 13
        if ($element->hasAttribute('vocab') && ($context instanceof RdfaLiteContext)) {
83 10
            $defaultVocabulary = new Vocabulary($element->getAttribute('vocab'));
84 10
            $context = $context->setDefaultVocabulary($defaultVocabulary);
85
        }
86
87 13
        return $context;
88
    }
89
90
    /**
91
     * Process vocabulary prefixes
92
     *
93
     * @param \DOMElement $element DOM element
94
     * @param ContextInterface $context Inherited Context
95
     * @return ContextInterface Local context for this element
96
     */
97 13
    protected function processPrefix(\DOMElement $element, ContextInterface $context)
98
    {
99 13
        if ($element->hasAttribute('prefix') && ($context instanceof RdfaLiteContext)) {
100 8
            $prefixes = preg_split('/\s+/', $element->getAttribute('prefix'));
101 8
            while (count($prefixes)) {
102 8
                $prefix = rtrim(array_shift($prefixes), ':');
103 8
                $uri = array_shift($prefixes);
104 8
                $context = $context->registerVocabulary($prefix, $uri);
105
            }
106
        }
107
108 13
        return $context;
109
    }
110
111
    /**
112
     * Create a property
113
     *
114
     * @param \DOMElement $element DOM element
115
     * @param ContextInterface $context Inherited Context
116
     * @return ContextInterface Local context for this element
117
     */
118 13
    protected function processProperty(\DOMElement $element, ContextInterface $context)
119
    {
120 13
        if ($element->hasAttribute('property') && !($context->getParentThing() instanceof RootThing)) {
121 7
            $properties = preg_split('/\s+/', $element->getAttribute('property'));
122 7
            foreach ($properties as $index => $property) {
123 7
                list($prefix, $name) = $this->getPrefixName($property);
124 7
                $context = $this->processPropertyPrefixName(
125
                    $prefix,
126
                    $name,
127
                    $element,
128
                    $context,
129 7
                    $index == (count($properties) - 1)
130
                );
131
            }
132
        }
133
134 13
        return $context;
135
    }
136
137
    /**
138
     * Split a value into a vocabulary prefix and a name
139
     *
140
     * @param string $prefixName Prefixed name
141
     * @return array Prefix and name
142
     */
143 13
    protected function getPrefixName($prefixName)
144
    {
145 13
        $prefixName = explode(':', $prefixName);
146 13
        $name = array_pop($prefixName);
147 13
        $prefix = array_pop($prefixName);
148 13
        return [$prefix, $name];
149
    }
150
151
    /**
152
     * Create a nested child
153
     *
154
     * @param \DOMElement $element DOM element
155
     * @param ContextInterface $context Context
156
     * @return ContextInterface Context for children
157
     */
158 13
    protected function processChild(\DOMElement $element, ContextInterface $context)
159
    {
160 13
        if ($element->hasAttribute('typeof')
161 13
            && (empty($element->getAttribute('property')) || $context->getParentThing() instanceof RootThing)
162
        ) {
163 13
            $context = $this->createAndAddChild($element, $context);
164
        }
165
166 13
        return $context;
167
    }
168
169
    /**
170
     * Create and add a nested child
171
     *
172
     * @param \DOMElement $element DOM element
173
     * @param ContextInterface $context Context
174
     * @return ContextInterface Context for children
175
     */
176 13
    protected function createAndAddChild(\DOMElement $element, ContextInterface $context)
177
    {
178 13
        $thing = $this->getThing(
179 13
            $element->getAttribute('typeof'),
180 13
            trim($element->getAttribute('resource')) ?: null,
181 13
            $context
182
        );
183
184
        // Add the new thing as a child to the current context
185
        // and set the thing as parent thing for nested iterations
186 7
        return $context->addChild($thing)->setParentThing($thing);
187
    }
188
189
190
    /**
191
     * Return a property child value
192
     *
193
     * @param \DOMElement $element DOM element
194
     * @param ContextInterface $context Context
195
     * @return ThingInterface|null Property child value
196
     */
197 7
    protected function getPropertyChildValue(\DOMElement $element, ContextInterface $context)
198
    {
199
        // If the property creates a new thing
200 7
        if ($element->hasAttribute('typeof')) {
201 4
            return $this->getThing(
202 4
                $element->getAttribute('typeof'),
203 4
                trim($element->getAttribute('resource')) ?: null,
204 4
                $context
205
            );
206
        }
207
208 7
        return null;
209
    }
210
211
    /**
212
     * Return the resource ID
213
     *
214
     * @param \DOMElement $element DOM element
215
     * @return string|null Resource ID
216
     */
217 7
    protected function getResourceId(\DOMElement $element)
218
    {
219 7
        return trim($element->getAttribute('resource')) ?: null;
220
    }
221
222
    /**
223
     * Return a vocabulary by prefix with fallback to the default vocabulary
224
     *
225
     * @param string $prefix Vocabulary prefix
226
     * @param ContextInterface $context Context
227
     * @return VocabularyInterface Vocabulary
228
     */
229 13
    protected function getVocabulary($prefix, ContextInterface $context)
230
    {
231 13
        return (empty($prefix) || !($context instanceof RdfaLiteContext)) ?
232 13
            $context->getDefaultVocabulary() : $context->getVocabulary($prefix);
233
    }
234
}
235