Passed
Push — master ( 724be3...506a08 )
by
unknown
03:41
created

ConstraintsComponent::checkVersionConstraint()   B

Complexity

Conditions 6
Paths 18

Size

Total Lines 42
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 22
c 0
b 0
f 0
nc 18
nop 4
dl 0
loc 42
rs 8.9457
1
<?php
2
/**
3
 * Copyright © Vaimo Group. All rights reserved.
4
 * See LICENSE_VAIMO.txt for license details.
5
 */
6
namespace Vaimo\ComposerPatches\Patch\DefinitionList\LoaderComponents;
7
8
use Vaimo\ComposerPatches\Patch\Definition as PatchDefinition;
9
10
class ConstraintsComponent implements \Vaimo\ComposerPatches\Interfaces\DefinitionListLoaderComponentInterface
11
{
12
    /**
13
     * @var \Vaimo\ComposerPatches\Interfaces\PackageConfigExtractorInterface
14
     */
15
    private $configExtractor;
16
17
    /**
18
     * @var \Composer\Package\Version\VersionParser
19
     */
20
    private $versionParser;
21
22
    /**
23
     * @var \Vaimo\ComposerPatches\Utils\ConstraintUtils
24
     */
25
    private $constraintUtils;
26
27
    /**
28
     * @var \Vaimo\ComposerPatches\Utils\PackageUtils
29
     */
30
    private $packageUtils;
31
32
    /**
33
     * @param \Vaimo\ComposerPatches\Interfaces\PackageConfigExtractorInterface $configExtractor
34
     */
35
    public function __construct(
36
        \Vaimo\ComposerPatches\Interfaces\PackageConfigExtractorInterface $configExtractor
37
    ) {
38
        $this->configExtractor = $configExtractor;
39
        $this->versionParser = new \Composer\Package\Version\VersionParser();
40
        $this->constraintUtils = new \Vaimo\ComposerPatches\Utils\ConstraintUtils();
41
        $this->packageUtils = new \Vaimo\ComposerPatches\Utils\PackageUtils();
42
    }
43
44
    /**
45
     * @param array $patches
46
     * @param \Composer\Package\PackageInterface[] $packagesByName
47
     * @return array
48
     */
49
    public function process(array $patches, array $packagesByName)
50
    {
51
        $rootPackages = array_filter(
52
            $packagesByName,
53
            function ($package) {
54
                return $package instanceof \Composer\Package\RootPackageInterface;
55
            }
56
        );
57
58
        /** @var \Composer\Package\CompletePackageInterface $rootPackage */
59
        $rootPackage = reset($rootPackages);
60
61
        $rootRequires = array_replace(
62
            $rootPackage->getRequires(),
63
            $rootPackage->getDevRequires()
64
        );
65
66
        foreach ($patches as $target => &$packagePatches) {
67
            foreach ($packagePatches as &$patchData) {
68
                if ($target !== PatchDefinition::BUNDLE_TARGET && !isset($packagesByName[$target])) {
69
                    $patchData = false;
70
                    continue;
71
                }
72
73
                $patchConstraints = $patchData[PatchDefinition::DEPENDS];
74
75
                $comparisonResults = $this->resolveComparisonResults(
76
                    $patchConstraints,
77
                    $packagesByName,
78
                    $rootRequires
79
                );
80
81
                if (count($patchConstraints) !== count(array_filter($comparisonResults))) {
82
                    $patchData = false;
83
                }
84
            }
85
86
            $packagePatches = array_filter($packagePatches);
87
        }
88
89
        return array_filter($patches);
90
    }
91
92
    private function resolveComparisonResults(array $patchConstraints, array $packages, array $rootRequires)
93
    {
94
        $comparisonResults = array();
95
96
        foreach ($patchConstraints as $constraintTarget => $constraint) {
97
            // Check if this is a negated dependency (array format)
98
            if (is_array($constraint) && isset($constraint['negated']) && $constraint['negated']) {
99
                $version = $constraint['version'];
100
                $packageExists = isset($packages[$constraintTarget]);
101
102
                if (!$packageExists) {
103
                    // Package not installed - negated dependency satisfied
104
                    $comparisonResults[] = true;
105
                    continue;
106
                }
107
108
                // Package is installed - check if version constraint fails
109
                $package = $packages[$constraintTarget];
110
                $matchResult = $this->checkVersionConstraint($package, $version, $rootRequires, $constraintTarget);
111
                $comparisonResults[] = !$matchResult; // Negate the result
112
                continue;
113
            }
114
115
            // Handle regular string constraints
116
            $version = $constraint;
117
118
            if (!isset($packages[$constraintTarget])) {
119
                continue;
120
            }
121
122
            $package = $packages[$constraintTarget];
123
124
            $matchResult = $this->checkVersionConstraint($package, $version, $rootRequires, $constraintTarget);
125
            $comparisonResults[] = $matchResult;
126
        }
127
128
        return $comparisonResults;
129
    }
130
131
    private function checkVersionConstraint($package, $version, $rootRequires, $constraintTarget)
132
    {
133
        $packageVersion = $package->getVersion();
134
        $packageVersions = array($package->getVersion());
135
136
        if (isset($rootRequires[$constraintTarget])) {
137
            /** @var \Composer\Package\CompletePackageInterface $targetRootPackage */
138
            $targetRootPackage = $rootRequires[$constraintTarget];
139
140
            $prettyVersion = $this->packageUtils->getPrettyVersion($targetRootPackage);
141
142
            $matches = array();
143
            preg_match('/.* as (.*)$/', $prettyVersion, $matches);
144
145
            if (isset($matches[1])) {
146
                $packageVersions[] = $matches[1];
147
            }
148
        }
149
150
        if ($this->constraintUtils->isDevConstraint($packageVersion)) {
151
            $definedVersion = $this->configExtractor->getConfig(
152
                $package,
153
                'version'
154
            );
155
156
            $packageVersions[] = $definedVersion;
157
        }
158
159
        $matchResult = false;
160
161
        foreach (array_filter($packageVersions) as $packageVersion) {
162
            $packageConstraint = $this->versionParser->parseConstraints($packageVersion);
163
            $patchConstraint = $this->versionParser->parseConstraints($version);
164
165
            $matchResult = $patchConstraint->matches($packageConstraint);
166
167
            if ($matchResult) {
168
                break;
169
            }
170
        }
171
172
        return $matchResult;
173
    }
174
}
175