DependencyGraph::getAggregatePackageContaining()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 5
nc 3
nop 1
1
<?php
2
3
/*
4
 * Copyright 2012 Johannes M. Schmitt <[email protected]>
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
namespace JMS\Composer\Graph;
20
21
use JMS\Composer\Graph\PackageNode;
22
23
/**
24
 * Graph of dependencies.
25
 *
26
 * @author Johannes M. Schmitt <[email protected]>
27
 */
28
class DependencyGraph
29
{
30
    /**
31
     * @var PackageNode[]
32
     */
33
    private $packages = array();
34
    /**
35
     * @var PackageNode
36
     */
37
    private $rootPackage;
38
39
    /**
40
     * @param PackageNode|null $rootPackage
41
     */
42
    public function __construct(PackageNode $rootPackage = null)
43
    {
44
        if (null !== $rootPackage) {
45
            $this->packages[strtolower($rootPackage->getName())] = $rootPackage;
46
        }
47
48
        $this->rootPackage = $rootPackage ?: $this->getOrCreate('__root');
49
    }
50
51
    /**
52
     * @return PackageNode
53
     */
54
    public function getRootPackage()
55
    {
56
        return $this->rootPackage;
57
    }
58
59
    /**
60
     * @param PackageNode $node
61
     *
62
     * @return bool
63
     */
64
    public function isRootPackage(PackageNode $node)
65
    {
66
        return $node === $this->rootPackage;
67
    }
68
69
    /**
70
     * @param string $name
71
     * @return bool
72
     */
73
    public function isRootPackageName($name)
74
    {
75
        return strtolower($this->rootPackage->getName()) === strtolower($name);
76
    }
77
78
    /**
79
     * @return PackageNode[]
80
     */
81
    public function getPackages()
82
    {
83
        return $this->packages;
84
    }
85
86
    /**
87
     * @param string $name
88
     *
89
     * @return PackageNode|null
90
     */
91
    public function getPackage($name)
92
    {
93
        return isset($this->packages[$name = strtolower($name)]) ? $this->packages[$name] : null;
94
    }
95
96
    /**
97
     * @param string $name
98
     *
99
     * @return bool
100
     */
101
    public function hasPackage($name)
102
    {
103
        return isset($this->packages[strtolower($name)]);
104
    }
105
106
    /**
107
     * @param string $name
108
     * @param array  $data
109
     *
110
     * @throws \InvalidArgumentException
111
     * @return PackageNode
112
     */
113
    public function createPackage($name, array $data = array())
114
    {
115
        if (isset($this->packages[strtolower($name)])) {
116
            throw new \InvalidArgumentException(sprintf('The package "%s" already exists.', $name));
117
        }
118
119
        return $this->packages[strtolower($name)] = new PackageNode($name, $data);
120
    }
121
122
    /**
123
     * @param string $packageA
124
     * @param string $packageB
125
     * @param string $versionConstraint
126
     */
127
    public function connect($packageA, $packageB, $versionConstraint)
128
    {
129
        $nodeA = $this->getOrCreate($packageA);
130
        $nodeB = $this->getOrCreate($packageB);
131
132
        // Do not connect the same package
133
        if ($packageA === $packageB){
134
            return;
135
        }
136
137
        // Do not add duplicate connections.
138
        foreach ($nodeA->getOutEdges() as $edge) {
139
            if ($edge->getDestPackage() === $nodeB) {
140
                return;
141
            }
142
        }
143
144
        $edge = new DependencyEdge($nodeA, $nodeB, $versionConstraint);
145
        $nodeA->addOutEdge($edge);
146
        $nodeB->addInEdge($edge);
147
    }
148
149
    /**
150
     * Searches the graph for an aggregate package that contains the given package.
151
     *
152
     * @param string $packageName the name of the contained package
153
     *
154
     * @return PackageNode|null the aggregate package
155
     */
156
    public function getAggregatePackageContaining($packageName)
157
    {
158
        foreach ($this->packages as $packageNode) {
159
            if ($packageNode->replaces($packageName)) {
160
                return $packageNode;
161
            }
162
        }
163
164
        return null;
165
    }
166
167
    /**
168
     * @param string $package
169
     *
170
     * @return PackageNode
171
     */
172
    private function getOrCreate($package)
173
    {
174
        if (isset($this->packages[strtolower($package)])) {
175
            return $this->packages[strtolower($package)];
176
        }
177
178
        return $this->packages[strtolower($package)] = new PackageNode($package);
179
    }
180
}