Completed
Push — master ( 96d434...f2324b )
by Daniel
04:52 queued 55s
created

XmlDriver   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 97
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 3

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 11
lcom 0
cbo 3
dl 0
loc 97
rs 10
c 2
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
B loadMetadataFromFile() 0 58 5
A extractOptionSet() 0 6 2
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
        $use = 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
        libxml_use_internal_errors($use);
34
35
        $xpath = new \DOMXpath($dom);
36
        $xpath->registerNamespace('psict', self::XML_NAMESPACE);
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
                $shared = $this->extractOptionSet($xpath, $fieldEl, 'shared-options');
50
                $form = $this->extractOptionSet($xpath, $fieldEl, 'form-options');
51
                $view = $this->extractOptionSet($xpath, $fieldEl, 'view-options');
52
                $storage = $this->extractOptionSet($xpath, $fieldEl, 'storage-options');
53
54
                $propertyMetadata = new PropertyMetadata(
55
                    $class->getName(),
56
                    $fieldEl->getAttribute('name'),
57
                    $fieldEl->getAttribute('type'),
58
                    $fieldEl->getAttribute('role'),
59
                    $fieldEl->getAttribute('group'),
60
                    [
61
                        'shared' => $shared,
62
                        'form' => $form,
63
                        'view' => $view,
64
                        'storage' => $storage,
65
                    ]
66
                );
67
68
                $classMetadata->addPropertyMetadata($propertyMetadata);
69
            }
70
        }
71
72
        return $classMetadata;
73
    }
74
75
    private function extractOptionSet(\DOMXpath $xpath, \DOMElement $fieldEl, $type)
76
    {
77
        foreach ($xpath->query('./psict:' . $type, $fieldEl) as $setEl) {
78
            return $this->extractOptions($xpath, $setEl);
79
        }
80
    }
81
82
    private function extractOptions(\DOMXPath $xpath, \DOMElement $setEl)
83
    {
84
        $options = [];
85
86
        foreach ($xpath->query('./psict:option', $setEl) as $optionEl) {
87
            if ($optionEl->getAttribute('type') === 'collection') {
88
                $options[$optionEl->getAttribute('name')] = $this->extractOptions($xpath, $optionEl);
89
                continue;
90
            }
91
92
            $options[$optionEl->getAttribute('name')] = $optionEl->nodeValue;
93
        }
94
95
        return $options;
96
    }
97
98
    /**
99
     * {@inheritdoc}
100
     */
101
    public function getExtension()
102
    {
103
        return 'xml';
104
    }
105
}
106