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

Action::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
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
    // TODO: Extract to RequirementFileRepository
55
    private function getInstalledRequirements(): array
56
    {
57
        $lockFile = ComposerParser::parseLockfile(base_path('composer.lock'));
58
59
        $packages = $lockFile->getPackages()->getData();
60
        $devPackages = $lockFile->getPackagesDev()->getData();
61
        $platform = $lockFile->getPlatform()->getData();
62
        $devPlatform = $lockFile->getPlatformDev()->getData();
63
        foreach ($packages as &$package) {
64
            $package['isDevelopment'] = false;
65
        }
66
        foreach ($devPackages as &$package) {
67
            $package['isDevelopment'] = true;
68
        }
69
        $platforms = [];
70
        foreach ($platform as $name => $version) {
71
            $platforms[] = [
72
                'name' => $name,
73
                'version' => $version,
74
                'isDevelopment' => false,
75
            ];
76
        }
77
        foreach ($devPlatform as $name => $version) {
78
            $platforms[] = [
79
                'name' => $name,
80
                'version' => $version,
81
                'isDevelopment' => true,
82
            ];
83
        }
84
85
        return array_merge($packages, $devPackages, $platforms);
86
    }
87
88
    private function install(RequirementContract $requirement): JobContract
89
    {
90
        if ($this->isRequirementInstalled($requirement)) {
91
            throw ValidationException::withMessages([
92
                'name' => [
93
                    "Package `{$requirement}` already installed",
94
                ],
95
            ]);
96
        }
97
98
        $job = new Job(
99
            'RequirementInstall',
100
            Uuid::uuid4()->toString(),
101
            'Waiting',
102
            Carbon::now(),
103
            new Process(),
104
            $requirement
105
        );
106
107
        $this->jobs->store($job);
108
109
        event(new RequirementInstalling($requirement, $job));
110
111
        return $job;
112
    }
113
114
    private function uninstall(RequirementContract $requirement): JobContract
115
    {
116
        $installedRequirements = $this->getInstalledRequirements();
117
118
        $installedRequirement = Arr::first($installedRequirements, function (array $value) use ($requirement) {
119
            return $value['name'] === $requirement->getName();
120
        });
121
122
        if (is_null($installedRequirement)) {
123
            throw new NotFoundHttpException();
124
        }
125
126
        $requirement = Requirement::fromArray($installedRequirement);
127
128
        $job = new Job(
129
            'RequirementUninstall',
130
            Uuid::uuid4()->toString(),
131
            'Waiting',
132
            Carbon::now(),
133
            new Process(),
134
            $requirement
135
        );
136
137
        $this->jobs->store($job);
138
139
        event(new RequirementUninstalling($requirement, $job));
140
141
        return $job;
142
    }
143
144
    private function isRequirementInstalled(RequirementContract $requirement): bool
145
    {
146
        $installedRequirements = $this->getInstalledRequirements();
147
148
        $installedRequirement = Arr::first($installedRequirements, function (array $value) use ($requirement) {
149
            return $value['name'] === $requirement->getName();
150
        });
151
152
        return !is_null($installedRequirement)
153
            && $installedRequirement['version'] === $requirement->getVersion()
154
            && $installedRequirement['isDevelopment'] === $requirement->isDevelopment();
155
    }
156
}
157