PackageXmlParser::getElementPaths()   C
last analyzed

Complexity

Conditions 7
Paths 4

Size

Total Lines 29
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 7.0119

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 29
ccs 15
cts 16
cp 0.9375
rs 6.7272
cc 7
eloc 19
nc 4
nop 1
crap 7.0119
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