LinkManager::isLinked()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 2
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the composer-link plugin.
7
 *
8
 * Copyright (c) 2021-2022 Sander Visser <[email protected]>.
9
 *
10
 * For the full copyright and license information, please view the LICENSE.md
11
 * file that was distributed with this source code.
12
 *
13
 * @link https://github.com/SanderSander/composer-link
14
 */
15
16
namespace ComposerLink;
17
18
use Composer\Installer\InstallationManager;
19
use Composer\Package\PackageInterface;
20
use Composer\Repository\InstalledRepositoryInterface;
21
use Composer\Util\Filesystem;
22
use Composer\Util\Loop;
23
use Exception;
24
use React\Promise\PromiseInterface;
25
26
class LinkManager
27
{
28
    protected Filesystem $filesystem;
29
30
    protected Loop $loop;
31
32
    protected InstallationManager $installationManager;
33
34
    protected InstalledRepositoryInterface $installedRepository;
35
36
    public function __construct(
37
        Filesystem $filesystem,
38
        Loop $loop,
39
        InstallationManager $installationManager,
40
        InstalledRepositoryInterface $installedRepository
41
    ) {
42
        $this->filesystem = $filesystem;
43
        $this->loop = $loop;
44
        $this->installationManager = $installationManager;
45
        $this->installedRepository = $installedRepository;
46
    }
47
48
    /**
49
     * Checks if the given package is linked.
50
     */
51
    public function isLinked(LinkedPackage $linkedPackage): bool
52
    {
53
        return $this->filesystem->isSymlinkedDirectory($linkedPackage->getInstallationPath()) ||
54
        $this->filesystem->isJunction($linkedPackage->getInstallationPath());
55
    }
56
57
    /**
58
     * Links the package into the vendor directory.
59
     */
60
    public function linkPackage(LinkedPackage $linkedPackage): void
61
    {
62
        if (!is_null($linkedPackage->getOriginalPackage())) {
63
            $this->uninstall($linkedPackage->getOriginalPackage());
64
        }
65
        $this->install($linkedPackage->getPackage());
66
    }
67
68
    /**
69
     * Unlinks the package from the vendor directory.
70
     */
71
    public function unlinkPackage(LinkedPackage $linkedPackage): void
72
    {
73
        // Update the repository to the current situation
74
        if (!is_null($linkedPackage->getOriginalPackage())) {
75
            $this->installedRepository->removePackage($linkedPackage->getOriginalPackage());
76
        }
77
        $this->installedRepository->addPackage($linkedPackage->getPackage());
78
79
        $this->uninstall($linkedPackage->getPackage());
80
        if (!is_null($linkedPackage->getOriginalPackage())) {
81
            $this->install($linkedPackage->getOriginalPackage());
82
        }
83
    }
84
85
    protected function uninstall(PackageInterface $package): void
86
    {
87
        $installer = $this->installationManager->getInstaller($package->getType());
88
        try {
89
            $this->wait($installer->uninstall($this->installedRepository, $package));
90
        } catch (Exception $exception) {
91
            $this->wait($installer->cleanup('uninstall', $package));
92
            throw $exception;
93
        }
94
95
        $this->wait($installer->cleanup('uninstall', $package));
96
    }
97
98
    /**
99
     * Downloads and installs the given package
100
     * https://github.com/composer/composer/blob/2.0.0/src/Composer/Util/SyncHelper.php.
101
     */
102
    protected function install(PackageInterface $package): void
103
    {
104
        $installer = $this->installationManager->getInstaller($package->getType());
105
106
        try {
107
            $this->wait($installer->download($package));
108
            $this->wait($installer->prepare('install', $package));
109
            $this->wait($installer->install($this->installedRepository, $package));
110
        } catch (Exception $exception) {
111
            $this->wait($installer->cleanup('install', $package));
112
            throw $exception;
113
        }
114
115
        $this->wait($installer->cleanup('install', $package));
116
    }
117
118
    /**
119
     * Waits for promise to be finished.
120
     */
121
    protected function wait(?PromiseInterface $promise): void
122
    {
123
        if (!is_null($promise)) {
124
            $this->loop->wait([$promise]);
125
        }
126
    }
127
}
128