Completed
Push — 3.0 ( 7b88ef...9c9edc )
by Daniel
06:18
created

PackageXmlParser   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 139
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 96.3%

Importance

Changes 5
Bugs 3 Features 0
Metric Value
wmc 23
c 5
b 3
f 0
lcom 1
cbo 0
dl 0
loc 139
ccs 52
cts 54
cp 0.963
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
C parseMappings() 0 32 8
A getTargetsDefinitions() 0 13 3
A __construct() 0 4 1
A getMappings() 0 9 2
A getTargetPath() 0 9 2
C getElementPaths() 0 29 7
1
<?php
2
/**
3
 * Composer Magento Installer
4
 */
5
6
namespace MagentoHackathon\Composer\Magento\Parser;
7
8
/**
9
 * Parses Magento Connect 2.0 package.xml files
10
 *
11
 * Class PackageXmlParser
12
 * @package MagentoHackathon\Composer\Magento\Parser
13
 */
14
class PackageXmlParser implements Parser
15
{
16
17
    /**
18
     * @var \SplFileObject The package.xml file
19
     */
20
    protected $file = null;
21
22
    /**
23
     * @var array Map of package content types to path prefixes
24
     */
25
    protected $targets = array();
26
27
    /**
28
     * @param string $packageXmlFile
29
     */
30 6
    public function __construct($packageXmlFile)
31
    {
32 6
        $this->file = new \SplFileObject($packageXmlFile);
33 6
    }
34
35
    /**
36
     * @return array
37
     * @throws \ErrorException
38
     */
39 5
    public function getMappings()
40
    {
41 5
        if (!$this->file->isReadable()) {
42 1
            throw new \ErrorException(sprintf('Package file "%s" not readable', $this->file->getPathname()));
43
        }
44
45 4
        $map = $this->parseMappings();
46 4
        return $map;
47
    }
48
49
    /**
50
     * @throws \RuntimeException
51
     * @return array
52
     */
53 4
    protected function parseMappings()
54
    {
55 4
        $map = array();
56
57
        /** @var $package \SimpleXMLElement */
58 4
        $package = simplexml_load_file($this->file->getPathname());
59 4
        if (isset($package)) {
60 4
            foreach ($package->xpath('//contents/target') as $target) {
61
                try {
62 4
                    $basePath = $this->getTargetPath($target);
63
64 4
                    foreach ($target->children() as $child) {
65 4
                        foreach ($this->getElementPaths($child) as $elementPath) {
66 4
                            if (pathinfo($elementPath, PATHINFO_EXTENSION) == 'txt') {
67
                                continue;
68
                            }
69 4
                            $relativePath = str_replace('//', '/', $basePath . '/' . $elementPath);
70
                            //remove the any trailing './' or '.' from the targets base-path.
71 4
                            if (strpos($relativePath, './') === 0) {
72 4
                                $relativePath = substr($relativePath, 2);
73
                            }
74 4
                            $map[] = array($relativePath, $relativePath);
75
                        }
76
                    }
77 2
                } catch (\RuntimeException $e) {
78
                    // Skip invalid targets
79 4
                    continue;
80
                }
81
            }
82
        }
83 4
        return $map;
84
    }
85
86
    /**
87
     * @param \SimpleXMLElement $target
88
     * @return string
89
     * @throws \RuntimeException
90
     */
91 4
    protected function getTargetPath(\SimpleXMLElement $target)
92
    {
93 4
        $name = (string) $target->attributes()->name;
94 4
        $targets = $this->getTargetsDefinitions();
95 4
        if (! isset($targets[$name])) {
96 1
            throw new \RuntimeException('Invalid target type ' . $name);
97
        }
98 4
        return $targets[$name];
99
    }
100
101
    /**
102
     * @return array
103
     */
104 4
    protected function getTargetsDefinitions()
105
    {
106 4
        if (empty($this->targets)) {
107
            /** @var $targets \SimpleXMLElement */
108 4
            $targets = simplexml_load_file(__DIR__ . '/../../../../../res/target.xml');
109 4
            foreach ($targets as $target) {
110
                /** @var $target \SimpleXMLElement */
111 4
                $attributes = $target->attributes();
112 4
                $this->targets["{$attributes->name}"] = "{$attributes->uri}";
113
            }
114
        }
115 4
        return $this->targets;
116
    }
117
118
    /**
119
     * @param \SimpleXMLElement $element
120
     * @return array
121
     * @throws \RuntimeException
122
     */
123 4
    protected function getElementPaths(\SimpleXMLElement $element)
124
    {
125 4
        $type = $element->getName();
126 4
        $name = $element->attributes()->name;
0 ignored issues
show
Bug introduced by
The property name does not seem to exist in SimpleXMLElement.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
127 4
        $elementPaths = array();
128
129
        switch ($type) {
130 4
            case 'dir':
131 4
                if ($element->children()) {
132 4
                    foreach ($element->children() as $child) {
133 4
                        foreach ($this->getElementPaths($child) as $elementPath) {
134 4
                            $elementPaths[] = $name == '.' ? $elementPath : $name . '/' . $elementPath;
135
                        }
136
                    }
137
                } else {
138
                    $elementPaths[] = $name;
139
                }
140 4
                break;
141
142 4
            case 'file':
143 4
                $elementPaths[] = $name;
144 4
                break;
145
146
            default:
147 1
                throw new \RuntimeException('Unknown path type: ' . $type);
148
        }
149
150 4
        return $elementPaths;
151
    }
152
}
153