Completed
Push — master ( c612e7...f3e1c8 )
by Christian
06:23
created

SolverRunner   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 137
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Importance

Changes 1
Bugs 1 Features 0
Metric Value
wmc 8
lcom 1
cbo 13
dl 0
loc 137
rs 10
c 1
b 1
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 27 1
B getRequest() 0 38 6
A solve() 0 15 1
1
<?php
2
3
/**
4
 * This file is part of tenside/core.
5
 *
6
 * (c) Christian Schiffler <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 * This project is provided in good faith and hope to be usable by anyone.
12
 *
13
 * @package    tenside/core
14
 * @author     Christian Schiffler <[email protected]>
15
 * @copyright  2015 Christian Schiffler <[email protected]>
16
 * @license    https://github.com/tenside/core/blob/master/LICENSE MIT
17
 * @link       https://github.com/tenside/core
18
 * @filesource
19
 */
20
21
namespace Tenside\Core\Composer;
22
23
use Composer\Composer;
24
use Composer\DependencyResolver\DefaultPolicy;
25
use Composer\DependencyResolver\Operation\OperationInterface;
26
use Composer\DependencyResolver\Pool;
27
use Composer\DependencyResolver\Request;
28
use Composer\DependencyResolver\Solver;
29
use Composer\DependencyResolver\SolverProblemsException;
30
use Composer\Package\Link;
31
use Composer\Package\PackageInterface;
32
use Composer\Package\RootPackageInterface;
33
use Composer\Repository\CompositeRepository;
34
use Composer\Repository\InstalledArrayRepository;
35
use Composer\Repository\PlatformRepository;
36
use Composer\Semver\Constraint\Constraint;
37
38
/**
39
 * This class is resolving dependencies.
40
 */
41
class SolverRunner
42
{
43
    /**
44
     * The composer instance.
45
     *
46
     * @var Composer
47
     */
48
    private $composer;
49
50
    /**
51
     * The root package.
52
     *
53
     * @var RootPackageInterface
54
     */
55
    private $package;
56
57
    /**
58
     * The built pool.
59
     *
60
     * @var Pool
61
     */
62
    private $pool;
63
64
    /**
65
     * The platform repository.
66
     *
67
     * @var PlatformRepository
68
     */
69
    private $platform;
70
71
    /**
72
     * The repository reflecting the current installation.
73
     *
74
     * @var CompositeRepository
75
     */
76
    private $installed;
77
78
    /**
79
     * Create a new instance.
80
     *
81
     * @param Composer $composer The composer instance.
82
     */
83
    public function __construct(Composer $composer)
84
    {
85
        // clone root package to have one in the installed repo that does not require anything
86
        // we don't want it to be uninstallable, but its requirements should not conflict
87
        // with the lock file for example
88
        $this->composer = $composer;
89
        $this->package  = $this->composer->getPackage();
90
        $installedRoot  = clone $this->package;
91
        $installedRoot->setRequires([]);
92
        $installedRoot->setDevRequires([]);
93
94
        $this->pool      = new Pool($this->package->getMinimumStability(), $this->package->getStabilityFlags());
95
        $this->platform  = new PlatformRepository();
96
        $this->installed = new CompositeRepository(
97
            [
98
                new InstalledArrayRepository(array($installedRoot)),
99
                $this->composer->getRepositoryManager()->getLocalRepository(),
100
                $this->platform
101
            ]
102
        );
103
104
        $this->pool->addRepository(
105
            new CompositeRepository(
106
                array_merge([$this->installed], $this->composer->getRepositoryManager()->getRepositories())
107
            )
108
        );
109
    }
110
111
    /**
112
     * Build a new request preserving the current requires.
113
     *
114
     * @return Request
115
     */
116
    private function getRequest()
117
    {
118
        $request = new Request($this->pool);
0 ignored issues
show
Unused Code introduced by
The call to Request::__construct() has too many arguments starting with $this->pool.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
119
120
        $constraint = new Constraint('=', $this->package->getVersion());
121
        $constraint->setPrettyString($this->package->getPrettyVersion());
122
        $request->install($this->package->getName(), $constraint);
123
124
        $fixedPackages = $this->platform->getPackages();
125
126
        // fix the version of all platform packages + additionally installed packages
127
        // to prevent the solver trying to remove or update those
128
        /** @var  Link[] $provided */
129
        $provided = $this->package->getProvides();
130
        /** @var PackageInterface $package */
131
        foreach ($fixedPackages as $package) {
132
            $constraint = new Constraint('=', $package->getVersion());
133
            $constraint->setPrettyString($package->getPrettyVersion());
134
135
            // skip platform packages that are provided by the root package
136
            if (($package->getRepository() !== $this->platform)
137
                || !isset($provided[$package->getName()])
138
                || !$provided[$package->getName()]->getConstraint()->matches($constraint)
139
            ) {
140
                $request->fix($package->getName(), $constraint);
141
            }
142
        }
143
144
        // add requirements
145
        $links = array_merge($this->package->getRequires(), $provided);
146
        /** @var Link $link */
147
        foreach ($links as $link) {
148
            // FIXME: can't we also fix these here? Could be faster.
0 ignored issues
show
Coding Style introduced by
Comment refers to a FIXME task "can't we also fix these here? Could be faster"
Loading history...
149
            $request->install($link->getTarget(), $link->getConstraint());
150
        }
151
152
        return $request;
153
    }
154
155
    /**
156
     * Solve the current dependencies and return the tasks that will be performed.
157
     *
158
     * @return OperationInterface[]
159
     *
160
     * @throws SolverProblemsException When the dependencies can not be resolved.
161
     */
162
    public function solve()
163
    {
164
        gc_collect_cycles();
165
        gc_disable();
166
167
        $solver  = new Solver(new DefaultPolicy($this->package->getPreferStable()), $this->pool, $this->installed);
168
        $request = $this->getRequest();
169
        $request->updateAll();
170
171
        $operations = $solver->solve($request);
172
173
        gc_enable();
174
175
        return $operations;
176
    }
177
}
178