Completed
Push — 3.0 ( 46e3af...f23b72 )
by Daniel
03:20
created

PackageXmlParser::getElementPaths()   C

Complexity

Conditions 7
Paths 4

Size

Total Lines 29
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 7.0052
Metric Value
dl 0
loc 29
ccs 20
cts 21
cp 0.9524
rs 6.7272
cc 7
eloc 19
nc 4
nop 1
crap 7.0052
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 4
                            }
74 4
                            $map[] = array($relativePath, $relativePath);
75 4
                        }
76 4
                    }
77
78 4
                } catch (\RuntimeException $e) {
79
                    // Skip invalid targets
80 2
                    continue;
81
                }
82 4
            }
83 4
        }
84 4
        return $map;
85
    }
86
87
    /**
88
     * @param \SimpleXMLElement $target
89
     * @return string
90
     * @throws \RuntimeException
91
     */
92 4
    protected function getTargetPath(\SimpleXMLElement $target)
93
    {
94 4
        $name = (string) $target->attributes()->name;
95 4
        $targets = $this->getTargetsDefinitions();
96 4
        if (! isset($targets[$name])) {
97 1
            throw new \RuntimeException('Invalid target type ' . $name);
98
        }
99 4
        return $targets[$name];
100
    }
101
102
    /**
103
     * @return array
104
     */
105 4
    protected function getTargetsDefinitions()
106
    {
107 4
        if (empty($this->targets)) {
108
            /** @var $targets \SimpleXMLElement */
109 4
            $targets = simplexml_load_file(__DIR__ . '/../../../../../res/target.xml');
110 4
            foreach ($targets as $target) {
111
                /** @var $target \SimpleXMLElement */
112 4
                $attributes = $target->attributes();
113 4
                $this->targets["{$attributes->name}"] = "{$attributes->uri}";
114 4
            }
115 4
        }
116 4
        return $this->targets;
117
    }
118
119
    /**
120
     * @param \SimpleXMLElement $element
121
     * @return array
122
     * @throws \RuntimeException
123
     */
124 4
    protected function getElementPaths(\SimpleXMLElement $element)
125
    {
126 4
        $type = $element->getName();
127 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...
128 4
        $elementPaths = array();
129
130
        switch ($type) {
131 4
            case 'dir':
132 4
                if ($element->children()) {
133 4
                    foreach ($element->children() as $child) {
134 4
                        foreach ($this->getElementPaths($child) as $elementPath) {
135 4
                            $elementPaths[] = $name == '.' ? $elementPath : $name . '/' . $elementPath;
136 4
                        }
137 4
                    }
138 4
                } else {
139
                    $elementPaths[] = $name;
140
                }
141 4
                break;
142
143 4
            case 'file':
144 4
                $elementPaths[] = $name;
145 4
                break;
146
147 1
            default:
148 1
                throw new \RuntimeException('Unknown path type: ' . $type);
149 1
        }
150
151 4
        return $elementPaths;
152
    }
153
}
154