Completed
Push — 3.0 ( ac6a55...46111f )
by Daniel
02:19
created

PackageXmlParser   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 140
Duplicated Lines 6.43 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 96.3%

Importance

Changes 4
Bugs 2 Features 0
Metric Value
wmc 23
c 4
b 2
f 0
lcom 1
cbo 0
dl 9
loc 140
ccs 52
cts 54
cp 0.963
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getMappings() 9 9 2
C parseMappings() 0 33 8
A getTargetPath() 0 9 2
A getTargetsDefinitions() 0 13 3
C getElementPaths() 0 29 7

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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 5
    public function __construct($packageXmlFile)
31
    {
32 5
        $this->file = new \SplFileObject($packageXmlFile);
33 5
    }
34
35
    /**
36
     * @return array
37
     * @throws \ErrorException
38
     */
39 4 View Code Duplication
    public function getMappings()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
40
    {
41 4
        if (!$this->file->isReadable()) {
42 1
            throw new \ErrorException(sprintf('Package file "%s" not readable', $this->file->getPathname()));
43
        }
44
45 3
        $map = $this->parseMappings();
46 3
        return $map;
47
    }
48
49
    /**
50
     * @throws \RuntimeException
51
     * @return array
52
     */
53 3
    protected function parseMappings()
54
    {
55 3
        $map = array();
56
57
        /** @var $package \SimpleXMLElement */
58 3
        $package = simplexml_load_file($this->file->getPathname());
59 3
        if (isset($package)) {
60 3
            foreach ($package->xpath('//contents/target') as $target) {
61
                try {
62 3
                    $basePath = $this->getTargetPath($target);
63
64 3
                    foreach ($target->children() as $child) {
65 3
                        foreach ($this->getElementPaths($child) as $elementPath) {
66 3
                            if (pathinfo($elementPath, PATHINFO_EXTENSION) == 'txt') {
67
                                continue;
68
                            }
69 3
                            $relativePath = $basePath . '/' . $elementPath;
70
                            //remove the any trailing './' or '.' from the targets base-path.
71 3
                            if (strpos($relativePath, './') === 0) {
72 3
                                $relativePath = substr($relativePath, 2);
73
                            }
74 3
                            $map[] = array($relativePath, $relativePath);
75
                        }
76
                    }
77
78 2
                } catch (\RuntimeException $e) {
79
                    // Skip invalid targets
80 3
                    continue;
81
                }
82
            }
83
        }
84 3
        return $map;
85
    }
86
87
    /**
88
     * @param \SimpleXMLElement $target
89
     * @return string
90
     * @throws \RuntimeException
91
     */
92 3
    protected function getTargetPath(\SimpleXMLElement $target)
93
    {
94 3
        $name = (string) $target->attributes()->name;
95 3
        $targets = $this->getTargetsDefinitions();
96 3
        if (! isset($targets[$name])) {
97 1
            throw new \RuntimeException('Invalid target type ' . $name);
98
        }
99 3
        return $targets[$name];
100
    }
101
102
    /**
103
     * @return array
104
     */
105 3
    protected function getTargetsDefinitions()
106
    {
107 3
        if (empty($this->targets)) {
108
            /** @var $targets \SimpleXMLElement */
109 3
            $targets = simplexml_load_file(__DIR__ . '/../../../../../res/target.xml');
110 3
            foreach ($targets as $target) {
111
                /** @var $target \SimpleXMLElement */
112 3
                $attributes = $target->attributes();
113 3
                $this->targets["{$attributes->name}"] = "{$attributes->uri}";
114
            }
115
        }
116 3
        return $this->targets;
117
    }
118
119
    /**
120
     * @param \SimpleXMLElement $element
121
     * @return array
122
     * @throws \RuntimeException
123
     */
124 3
    protected function getElementPaths(\SimpleXMLElement $element)
125
    {
126 3
        $type = $element->getName();
127 3
        $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 3
        $elementPaths = array();
129
130
        switch ($type) {
131 3
            case 'dir':
132 3
                if ($element->children()) {
133 3
                    foreach ($element->children() as $child) {
134 3
                        foreach ($this->getElementPaths($child) as $elementPath) {
135 3
                            $elementPaths[] = $name == '.' ? $elementPath : $name . '/' . $elementPath;
136
                        }
137
                    }
138
                } else {
139
                    $elementPaths[] = $name;
140
                }
141 3
                break;
142
143 1
            case 'file':
144 3
                $elementPaths[] = $name;
145 3
                break;
146
147
            default:
148 1
                throw new \RuntimeException('Unknown path type: ' . $type);
149
        }
150
151 3
        return $elementPaths;
152
    }
153
}
154