PackageConverter::getConstraint()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 9.2
c 0
b 0
f 0
cc 4
eloc 9
nc 4
nop 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
 * @author     Andreas Schempp <[email protected]>
16
 * @copyright  2015 Christian Schiffler <[email protected]>
17
 * @license    https://github.com/tenside/core/blob/master/LICENSE MIT
18
 * @link       https://github.com/tenside/core
19
 * @filesource
20
 */
21
22
namespace Tenside\Core\Composer;
23
24
use Composer\Package\CompletePackageInterface;
25
use Composer\Package\Link;
26
use Composer\Package\PackageInterface;
27
use Composer\Package\RootPackageInterface;
28
use Composer\Repository\RepositoryInterface;
29
use Tenside\Core\Util\JsonArray;
30
31
/**
32
 * The main entry point.
33
 */
34
class PackageConverter
35
{
36
    /**
37
     * The root package of the installation.
38
     *
39
     * @var RootPackageInterface
40
     */
41
    private $rootPackage;
42
43
    /**
44
     * Create a new instance.
45
     *
46
     * @param RootPackageInterface $rootPackage The root package of the installation.
47
     */
48
    public function __construct(RootPackageInterface $rootPackage)
49
    {
50
        $this->rootPackage = $rootPackage;
51
    }
52
53
    /**
54
     * Create a new instance and return it.
55
     *
56
     * @param RootPackageInterface $rootPackage The root package of the installation.
57
     *
58
     * @return PackageConverter
59
     */
60
    public static function create(RootPackageInterface $rootPackage)
61
    {
62
        return new static($rootPackage);
63
    }
64
65
    /**
66
     * Convert a package version into string representation.
67
     *
68
     * @param PackageInterface $package       The package to extract the version from.
69
     *
70
     * @param bool             $fullReference Flag if the complete reference shall be added or an abbreviated form.
71
     *
72
     * @return string
73
     *
74
     * @throws \RuntimeException If the package is a dev package and does not have valid reference information.
75
     */
76
    public static function convertPackageVersion(PackageInterface $package, $fullReference = false)
77
    {
78
        $version = $package->getPrettyVersion();
79
80
        if ('dev' === $package->getStability()) {
81
            if (null === ($reference = $package->getDistReference())) {
82
                if (null === ($reference = $package->getSourceReference())) {
83
                    throw new \RuntimeException('Unable to determine reference for ' . $package->getPrettyName());
84
                }
85
            }
86
87
            $version .= '#' . (!$fullReference ? substr($reference, 0, 8) : $reference);
88
        }
89
90
        return $version;
91
    }
92
93
    /**
94
     * Convert a package to array information used by json API.
95
     *
96
     * @param PackageInterface      $package The package to convert.
97
     *
98
     * @param null|PackageInterface $upgrade The package to show as upgradable to.
99
     *
100
     * @return JsonArray
101
     */
102
    public function convertPackageToArray(PackageInterface $package, PackageInterface $upgrade = null)
103
    {
104
        $name = $package->getPrettyName();
105
        $data = new JsonArray([
106
            'name'       => $name,
107
            'version'    => $this->convertPackageVersion($package),
108
            'constraint' => $this->getConstraint($name),
109
            'type'       => $package->getType(),
110
            'locked'     => $this->isLocked($name),
111
        ]);
112
113
        if (null !== ($releaseDate = $package->getReleaseDate())) {
114
            $data->set('time', $releaseDate->format(\DateTime::ATOM));
115
        }
116
117
        if (null !== $upgrade) {
118
            $data->set('upgrade_version', $upgrade->getPrettyVersion());
119
            if (null !== ($upgradeReleaseDate = $upgrade->getReleaseDate())) {
120
                $data->set('upgrade_time', $upgradeReleaseDate->format(\DateTime::ATOM));
121
            }
122
        }
123
124
        if ($package instanceof CompletePackageInterface) {
125
            $this->convertCompletePackage($package, $data);
126
        }
127
128
        return $data;
129
    }
130
131
    /**
132
     * Convert the information of all packages in a repository to an array used by json API.
133
     *
134
     * @param RepositoryInterface      $repository   The repository holding the packages to convert.
135
     *
136
     * @param bool                     $requiredOnly If true, return only the packages added to the root package as
137
     *                                               require.
138
     *
139
     * @param null|RepositoryInterface $upgradeList  The packages available as upgrades.
140
     *
141
     * @return JsonArray
142
     */
143
    public function convertRepositoryToArray(
144
        RepositoryInterface $repository,
145
        $requiredOnly = false,
146
        RepositoryInterface $upgradeList = null
147
    ) {
148
        $requires = $requiredOnly ? $this->rootPackage->getRequires() : false;
149
        $packages = new JsonArray();
150
        /** @var \Composer\Package\PackageInterface $package */
151
        foreach ($repository->getPackages() as $package) {
152
            $name = $package->getPrettyName();
153
            $esc  = $packages->escape($name);
154
            if (false === $requires || (isset($requires[$name]))) {
155
                $upgradePkg = null;
156
                if ($upgradeList) {
157
                    $upgradePkg = $upgradeList->findPackage($name, '*');
158
                }
159
                $packages->set(
160
                    $esc,
161
                    $this->convertPackageToArray($package, $upgradePkg)->getData()
162
                );
163
            }
164
        }
165
166
        return $packages;
167
    }
168
169
    /**
170
     * Check if a package is locked.
171
     *
172
     * @param string $packageName The name of the package to test.
173
     *
174
     * @return bool
175
     *
176
     * @see ComposerJson::isLocked()
177
     */
178
    private function isLocked($packageName)
179
    {
180
        $extra = $this->rootPackage->getExtra();
181
        return isset($extra['tenside']['version-locks'][$packageName]);
182
    }
183
184
    /**
185
     * Determine the constraint defined for a given package (if required via root project).
186
     *
187
     * @param string $packageName The name of the package to retrieve the constraint for.
188
     *
189
     * @return string|null
190
     */
191
    private function getConstraint($packageName)
192
    {
193
        $requires = $this->rootPackage->getRequires();
194
        if (isset($requires[$packageName])) {
195
            /** @var Link $link */
196
            $link = $requires[$packageName];
197
            return $link->getConstraint()->getPrettyString();
198
        }
199
200
        foreach ($requires as $link) {
201
            /** @var Link $link */
202
            if ($link->getTarget() == $packageName) {
203
                return $link->getConstraint()->getPrettyString();
204
            }
205
        }
206
207
        return null;
208
    }
209
210
    /**
211
     * Convert the data of a complete package to the passed json array.
212
     *
213
     * @param CompletePackageInterface $package The package to process.
214
     *
215
     * @param JsonArray                $data    The json array to push the data to.
216
     *
217
     * @return void
218
     */
219
    private function convertCompletePackage(CompletePackageInterface $package, $data)
220
    {
221
        $data->set('description', $package->getDescription());
222
        $data->set('license', $package->getLicense());
223
        if ($keywords = $package->getKeywords()) {
224
            $data->set('keywords', $keywords);
225
        }
226
        if ($homepage = $package->getHomepage()) {
227
            $data->set('homepage', $homepage);
228
        }
229
        if ($authors = $package->getAuthors()) {
230
            $data->set('authors', $authors);
231
        }
232
        if ($support = $package->getSupport()) {
233
            $data->set('support', $support);
234
        }
235
        if ($extra = $package->getExtra()) {
236
            $data->set('extra', $extra);
237
        }
238
        $data->set('abandoned', $package->isAbandoned());
239
        if ($package->isAbandoned()) {
240
            $data->set('replacement', $package->getReplacementPackage());
241
        }
242
    }
243
}
244