Completed
Push — master ( 573c79...8e56f4 )
by Christian
02:40
created

PackageConverter::convertPackageToArray()   B

Complexity

Conditions 4
Paths 8

Size

Total Lines 25
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 25
rs 8.5806
cc 4
eloc 15
nc 8
nop 2
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|string      $upgradeVersion The package version to show as upgradable to.
99
     *
100
     * @return JsonArray
101
     */
102
    public function convertPackageToArray(PackageInterface $package, $upgradeVersion = 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 !== $upgradeVersion) {
118
            $data->set('upgrade_version', $upgradeVersion);
119
        }
120
121
        if ($package instanceof CompletePackageInterface) {
122
            $this->convertCompletePackage($package, $data);
123
        }
124
125
        return $data;
126
    }
127
128
    /**
129
     * Convert the information of all packages in a repository to an array used by json API.
130
     *
131
     * @param RepositoryInterface $repository   The repository holding the packages to convert.
132
     *
133
     * @param bool                $requiredOnly If true, return only the packages added to the root package as require.
134
     *
135
     * @param null|JsonArray      $upgradeList  The package version to show as upgradable to.
136
     *
137
     * @return JsonArray
138
     */
139
    public function convertRepositoryToArray(
140
        RepositoryInterface $repository,
141
        $requiredOnly = false,
142
        JsonArray $upgradeList = null
143
    ) {
144
        $requires = $requiredOnly ? $this->rootPackage->getRequires() : false;
145
        $packages = new JsonArray();
146
        /** @var \Composer\Package\PackageInterface $package */
147
        foreach ($repository->getPackages() as $package) {
148
            $name = $package->getPrettyName();
149
            $esc  = $packages->escape($name);
150
            if (false === $requires || (isset($requires[$name]))) {
151
                $upgradeVersion = null;
152
                if ($upgradeList && $upgradeList->has($esc)) {
153
                    $upgradeVersion = $upgradeList->get($esc);
154
                }
155
                $packages->set(
156
                    $esc,
157
                    $this->convertPackageToArray($package, $upgradeVersion)->getData()
158
                );
159
            }
160
        }
161
162
        return $packages;
163
    }
164
165
    /**
166
     * Compare two packages by their names.
167
     *
168
     * @param array $left  The first package for comparison.
169
     *
170
     * @param array $right The second package for comparison.
171
     *
172
     * @return int
173
     *
174
     * @internal
175
     */
176
    public function packageCompare($left, $right)
177
    {
178
        return strnatcasecmp($left['name'], $right['name']);
179
    }
180
181
    /**
182
     * Check if a package is locked.
183
     *
184
     * @param string $packageName The name of the package to test.
185
     *
186
     * @return bool
187
     *
188
     * @see ComposerJson::isLocked()
189
     */
190
    private function isLocked($packageName)
191
    {
192
        $extra = $this->rootPackage->getExtra();
193
        return isset($extra['tenside']['version-locks'][$packageName]);
194
    }
195
196
    /**
197
     * Determine the constraint defined for a given package (if required via root project).
198
     *
199
     * @param string $packageName The name of the package to retrieve the constraint for.
200
     *
201
     * @return string|null
202
     */
203
    private function getConstraint($packageName)
204
    {
205
        $requires = $this->rootPackage->getRequires();
206
        if (isset($requires[$packageName])) {
207
            /** @var Link $link */
208
            $link = $requires[$packageName];
209
            return $link->getConstraint()->getPrettyString();
210
        }
211
212
        foreach ($requires as $link) {
213
            /** @var Link $link */
214
            if ($link->getTarget() == $packageName) {
215
                return $link->getConstraint()->getPrettyString();
216
            }
217
        }
218
219
        return null;
220
    }
221
222
    /**
223
     * Convert the data of a complete package to the passed json array.
224
     *
225
     * @param CompletePackageInterface $package The package to process.
226
     *
227
     * @param JsonArray                $data    The json array to push the data to.
228
     *
229
     * @return void
230
     */
231
    private function convertCompletePackage(CompletePackageInterface $package, $data)
232
    {
233
        $data->set('description', $package->getDescription());
234
        $data->set('license', $package->getLicense());
235
        if ($keywords = $package->getKeywords()) {
236
            $data->set('keywords', $keywords);
237
        }
238
        if ($homepage = $package->getHomepage()) {
239
            $data->set('homepage', $homepage);
240
        }
241
        if ($authors = $package->getAuthors()) {
242
            $data->set('authors', $authors);
243
        }
244
        if ($support = $package->getSupport()) {
245
            $data->set('support', $support);
246
        }
247
        if ($extra = $package->getExtra()) {
248
            $data->set('extra', $extra);
249
        }
250
        $data->set('abandoned', $package->isAbandoned());
251
        if ($package->isAbandoned()) {
252
            $data->set('replacement', $package->getReplacementPackage());
253
        }
254
    }
255
}
256