Completed
Pull Request — master (#8)
by Anton
01:21
created

Action::getInstalledRequirement()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 16
rs 9.7333
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
/*
4
 * This file is part of Laravel Paket.
5
 *
6
 * (c) Anton Komarev <[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
12
declare(strict_types=1);
13
14
namespace Cog\Laravel\Paket\Http\Controllers\Api\Jobs\Post;
15
16
use Cog\Contracts\Paket\Job\Entities\Job as JobContract;
17
use Cog\Contracts\Paket\Job\Repositories\Job as JobRepositoryContract;
18
use Cog\Contracts\Paket\Requirement\Entities\Requirement as RequirementContract;
19
use Cog\Laravel\Paket\Job\Entities\Job;
20
use Cog\Laravel\Paket\Process\Entities\Process;
21
use Cog\Laravel\Paket\Requirement\Entities\Requirement;
22
use Cog\Laravel\Paket\Requirement\Events\RequirementInstalling;
23
use Cog\Laravel\Paket\Requirement\Events\RequirementUninstalling;
24
use Illuminate\Contracts\Support\Responsable as ResponsableContract;
25
use Illuminate\Support\Arr;
26
use Illuminate\Support\Carbon;
27
use Illuminate\Validation\ValidationException;
28
use MCStreetguy\ComposerParser\Factory as ComposerParser;
29
use Ramsey\Uuid\Uuid;
30
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
31
32
final class Action
33
{
34
    private $jobs;
35
36
    public function __construct(JobRepositoryContract $jobs)
37
    {
38
        $this->jobs = $jobs;
39
    }
40
41
    public function __invoke(Request $request): ResponsableContract
42
    {
43
        $requirement = Requirement::fromArray($request->input('requirement'));
44
45
        if ($request->input('type') === 'RequirementInstall') {
46
            $job = $this->install($requirement);
47
        } else {
48
            $job = $this->uninstall($requirement);
49
        }
50
51
        return new Response($job);
52
    }
53
54
    private function install(RequirementContract $requirement): JobContract
55
    {
56
        if ($this->isRequirementInstalled($requirement)) {
57
            throw ValidationException::withMessages([
58
                'name' => [
59
                    "Package `{$requirement}` already installed",
60
                ],
61
            ]);
62
        }
63
64
        $job = new Job(
65
            'RequirementInstall',
66
            Uuid::uuid4()->toString(),
67
            'Waiting',
68
            Carbon::now(),
69
            new Process(),
70
            $requirement
71
        );
72
73
        $this->jobs->store($job);
74
75
        event(new RequirementInstalling($requirement, $job));
76
77
        return $job;
78
    }
79
80
    private function uninstall(RequirementContract $requirement): JobContract
81
    {
82
        $requirement = $this->getInstalledRequirement($requirement);
83
84
        $job = new Job(
85
            'RequirementUninstall',
86
            Uuid::uuid4()->toString(),
87
            'Waiting',
88
            Carbon::now(),
89
            new Process(),
90
            $requirement
91
        );
92
93
        $this->jobs->store($job);
94
95
        event(new RequirementUninstalling($requirement, $job));
96
97
        return $job;
98
    }
99
100
    private function getInstalledRequirements(): array
101
    {
102
        $lockFile = ComposerParser::parseLockfile(base_path('composer.lock'));
103
104
        $packages = $lockFile->getPackages()->getData();
105
        $devPackages = $lockFile->getPackagesDev()->getData();
106
        $platform = $lockFile->getPlatform()->getData();
107
        $devPlatform = $lockFile->getPlatformDev()->getData();
108
        foreach ($packages as &$package) {
109
            $package['isDevelopment'] = false;
110
        }
111
        foreach ($devPackages as &$package) {
112
            $package['isDevelopment'] = true;
113
        }
114
        $platforms = [];
115
        foreach ($platform as $name => $version) {
116
            $platforms[] = [
117
                'name' => $name,
118
                'version' => $version,
119
                'isDevelopment' => false,
120
            ];
121
        }
122
        foreach ($devPlatform as $name => $version) {
123
            $platforms[] = [
124
                'name' => $name,
125
                'version' => $version,
126
                'isDevelopment' => true,
127
            ];
128
        }
129
130
        return array_merge($packages, $devPackages, $platforms);
131
    }
132
133
    private function getInstalledRequirement(RequirementContract $requirement): RequirementContract
134
    {
135
        $installedRequirements = $this->getInstalledRequirements();
136
137
        $installedRequirement = Arr::first($installedRequirements, function (array $value) use ($requirement) {
138
            return $value['name'] === $requirement->getName();
139
        });
140
141
        if (is_null($installedRequirement)) {
142
            throw new NotFoundHttpException();
143
        }
144
145
        $requirement = Requirement::fromArray($installedRequirement);
146
147
        return $requirement;
148
    }
149
150
    private function isRequirementInstalled(RequirementContract $requirement): bool
151
    {
152
        $installedRequirements = $this->getInstalledRequirements();
153
154
        $installedRequirement = Arr::first($installedRequirements, function (array $value) use ($requirement) {
155
            return $value['name'] === $requirement->getName();
156
        });
157
158
        return !is_null($installedRequirement)
159
            && $installedRequirement['version'] === $requirement->getVersion()
160
            && $installedRequirement['isDevelopment'] === $requirement->isDevelopment();
161
    }
162
}
163