Completed
Push — master ( 6552a7...80126e )
by Daniel
11s
created

XmlDriver   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 81
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 3

Importance

Changes 0
Metric Value
wmc 9
lcom 0
cbo 3
dl 0
loc 81
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
B loadMetadataFromFile() 0 49 5
A extractOptions() 0 15 3
A getExtension() 0 4 1
1
<?php
2
3
namespace Psi\Component\ContentType\Metadata\Driver;
4
5
use Metadata\Driver\AbstractFileDriver;
6
use Psi\Component\ContentType\Metadata\ClassMetadata;
7
use Psi\Component\ContentType\Metadata\PropertyMetadata;
8
9
class XmlDriver extends AbstractFileDriver
10
{
11
    const XML_NAMESPACE = 'http://github.com/psiphp/content-type/mapping';
12
13
    /**
14
     * {@inheritdoc}
15
     */
16
    public function loadMetadataFromFile(\ReflectionClass $class, $path)
17
    {
18
        $classMetadata = new ClassMetadata($class->getName());
19
20
        libxml_use_internal_errors(true);
21
        $dom = new \DOMDocument('1.0');
22
        $dom->load($path);
23
24
        if (!$dom->schemaValidate(__DIR__ . '/../../../schema/mapping.xsd')) {
25
            $message = array_reduce(libxml_get_errors(), function ($foo, $error) {
26
                return $error->message;
27
            });
28
            throw new \InvalidArgumentException(sprintf(
29
                'Could not validate XML mapping at "%s": %s',
30
                $path, $message
31
            ));
32
        }
33
34
        $xpath = new \DOMXpath($dom);
35
        $xpath->registerNamespace('psict', self::XML_NAMESPACE);
36
37
38
        foreach ($xpath->query('//psict:class') as $classEl) {
39
            $classAttr = $classEl->getAttribute('name');
40
41
            if ($classAttr !== $class->getName()) {
42
                throw new \InvalidArgumentException(sprintf(
43
                    'Expected class name to be "%s" but it is mapped as "%s"',
44
                    $class->getName(), $classAttr
45
                ));
46
            }
47
48
            foreach ($xpath->query('./psict:field', $classEl) as $fieldEl) {
49
                $options = $this->extractOptions($xpath, $fieldEl);
50
                $propertyMetadata = new PropertyMetadata(
51
                    $class->getName(),
52
                    $fieldEl->getAttribute('name'),
53
                    $fieldEl->getAttribute('type'),
54
                    $fieldEl->getAttribute('role'),
55
                    $fieldEl->getAttribute('group'),
56
                    $options
57
                );
58
59
                $classMetadata->addPropertyMetadata($propertyMetadata);
60
            }
61
        }
62
63
        return $classMetadata;
64
    }
65
66
    private function extractOptions(\DOMXPath $xpath, \DOMElement $fieldEl)
67
    {
68
        $options = [];
69
70
        foreach ($xpath->query('./psict:option', $fieldEl) as $optionEl) {
71
            if ($optionEl->getAttribute('type') === 'collection') {
72
                $options[$optionEl->getAttribute('name')] = $this->extractOptions($xpath, $optionEl);
73
                continue;
74
            }
75
76
            $options[$optionEl->getAttribute('name')] = $optionEl->nodeValue;
77
        }
78
79
        return $options;
80
    }
81
82
    /**
83
     * {@inheritdoc}
84
     */
85
    public function getExtension()
86
    {
87
        return 'xml';
88
    }
89
}
90