Installer::initializeVendorDir()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
ccs 0
cts 0
cp 0
crap 2
rs 10
1
<?php
2
/**
3
 * Plugins Management
4
 * @author Joe Huss <[email protected]>
5
 * @copyright 2019
6
 * @package MyAdmin
7
 * @category Plugins
8
 */
9
10
/**
11
 * MyAdmin Installer Plugin
12
 *
13
 * The InstallerInterface class defines the following methods (please see the source for the exact signature):
14
 *   supports(), here you test whether the passed type matches the name that you declared for this installer (see the example).
15
 *   isInstalled(), determines whether a supported package is installed or not.
16
 *   install(), here you can determine the actions that need to be executed upon installation.
17
 *   update(), here you define the behavior that is required when Composer is invoked with the update argument.
18
 *   uninstall(), here you can determine the actions that need to be executed when the package needs to be removed.
19
 *   getInstallPath(), this method should return the location where the package is to be installed, relative from the location of composer.json.
20
 *
21
 * Implements https://github.com/composer/composer/blob/master/src/Composer/Installer/InstallerInterface.php
22
 *
23
 */
24
25
namespace MyAdmin\Plugins;
26
27
use Composer\Composer;
28
use Composer\Installer\BinaryInstaller;
29
use Composer\Installer\LibraryInstaller;
30
use Composer\IO\IOInterface;
31
use Composer\Package\PackageInterface;
32
use Composer\Util\Filesystem;
33
use Composer\Util\Silencer;
34
use Composer\Repository\InstalledRepositoryInterface;
35
36
/**
37
 * Class Installer
38
 *
39
 * @package MyAdmin\Plugins
40
 */
41
class Installer extends LibraryInstaller
42
{
43
	protected $templateDir;
44
45
	/**
46
	 * Initializes library installer.
47
	 *
48
	 * @param IOInterface     $io
0 ignored issues
show
Bug introduced by
The type Composer\IO\IOInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
49
	 * @param Composer        $composer
0 ignored issues
show
Bug introduced by
The type Composer\Composer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
50
	 * @param string          $type
51
	 * @param Filesystem      $filesystem
0 ignored issues
show
Bug introduced by
The type Composer\Util\Filesystem was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
52
	 * @param BinaryInstaller $binaryInstaller
0 ignored issues
show
Bug introduced by
The type Composer\Installer\BinaryInstaller was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
53
	 */
54
	public function __construct(IOInterface $io, Composer $composer, $type = 'library', Filesystem $filesystem = null, BinaryInstaller $binaryInstaller = null)
55
	{
56
		$this->composer = $composer;
0 ignored issues
show
Bug Best Practice introduced by
The property composer does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
57
		$this->downloadManager = $composer->getDownloadManager();
0 ignored issues
show
Bug Best Practice introduced by
The property downloadManager does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
58
		$this->io = $io;
0 ignored issues
show
Bug Best Practice introduced by
The property io does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
59
		$this->type = $type;
0 ignored issues
show
Bug Best Practice introduced by
The property type does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
60
		$this->filesystem = $filesystem ?: new Filesystem();
0 ignored issues
show
Bug Best Practice introduced by
The property filesystem does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
61
		$this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
0 ignored issues
show
Bug Best Practice introduced by
The property vendorDir does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
62
		$this->templateDir = $this->vendorDir.'/../include/templates';
63
		$this->binaryInstaller = $binaryInstaller ?: new BinaryInstaller($this->io, rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $this->filesystem);
0 ignored issues
show
Bug Best Practice introduced by
The property binaryInstaller does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
64
	}
65
66
	/**
67
	 * {@inheritDoc}
68
	 */
69
	public function supports($packageType)
70
	{
71
		return in_array($packageType, [
72
			'myadmin-template',
73
			'myadmin-module',
74
			'myadmin-plugin',
75
			'myadmin-menu'
76
		]);
77
		//return $packageType === $this->type || NULL === $this->type;
78
	}
79
80
81
	/**
82
	 * Checks that provided package is installed.
83
	 *
84
	 * @param InstalledRepositoryInterface $repo    repository in which to check
0 ignored issues
show
Bug introduced by
The type Composer\Repository\InstalledRepositoryInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
85
	 * @param PackageInterface             $package package instance
0 ignored issues
show
Bug introduced by
The type Composer\Package\PackageInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
86
	 *
87
	 * @return bool
88
	 */
89
	public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
90
	{
91
		return parent::isInstalled($repo, $package);
92
		//return $repo->hasPackage($package) && is_readable($this->getInstallPath($package));
93
	}
94
95
	/**
96
	 * {@inheritDoc}
97
	 */
98
	public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
99
	{
100
		$this->initializeVendorDir();
101
		$downloadPath = $this->getInstallPath($package);
102
		// remove the binaries if it appears the package files are missing
103
		if (!is_readable($downloadPath) && $repo->hasPackage($package)) {
104
			$this->binaryInstaller->removeBinaries($package);
105
		}
106
		$this->installCode($package);
107
		$this->binaryInstaller->installBinaries($package, $this->getInstallPath($package));
108
		if (!$repo->hasPackage($package)) {
109
			$repo->addPackage(clone $package);
110
		}
111
	}
112
113
	/**
114
	 * {@inheritDoc}
115
	 * @throws \InvalidArgumentException
116
	 */
117
	public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
118
	{
119
		if (!$repo->hasPackage($initial)) {
120
			throw new \InvalidArgumentException('Package is not installed: '.$initial);
121
		}
122
		$this->initializeVendorDir();
123
		$this->binaryInstaller->removeBinaries($initial);
124
		$this->updateCode($initial, $target);
125
		$this->binaryInstaller->installBinaries($target, $this->getInstallPath($target));
126
		$repo->removePackage($initial);
127
		if (!$repo->hasPackage($target)) {
128
			$repo->addPackage(clone $target);
129
		}
130
	}
131
132
	/**
133
	 * {@inheritDoc}
134
	 * @throws \InvalidArgumentException
135
	 */
136
	public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
137
	{
138
		if (!$repo->hasPackage($package)) {
139
			throw new \InvalidArgumentException('Package is not installed: '.$package);
140
		}
141
		$this->removeCode($package);
142
		$this->binaryInstaller->removeBinaries($package);
143
		$repo->removePackage($package);
144
		$downloadPath = $this->getPackageBasePath($package);
145
		if (mb_strpos($package->getName(), '/')) {
146
			$packageVendorDir = dirname($downloadPath);
147
			if (is_dir($packageVendorDir) && $this->filesystem->isDirEmpty($packageVendorDir)) {
148
				Silencer::call('rmdir', $packageVendorDir);
149
			}
150
		}
151
	}
152
153
	/**
154
	 * {@inheritDoc}
155
	 */
156
	public function getInstallPath(PackageInterface $package)
157
	{
158
		if ($this->type == 'myadmin-template') {
159
			$this->initializeTemplateDir();
160
			$basePath = ($this->templateDir ? $this->templateDir.'/' : '') . $package->getPrettyName();
161
		} else {
162
			$this->initializeVendorDir();
163
			$basePath = ($this->vendorDir ? $this->vendorDir.'/' : '') . $package->getPrettyName();
164
		}
165
		$targetDir = $package->getTargetDir();
166
		return $basePath . ($targetDir ? '/'.$targetDir : '');
167
	}
168
169
	/**
170
	 * Make sure binaries are installed for a given package.
171
	 *
172
	 * @param PackageInterface $package Package instance
173
	 */
174
	public function ensureBinariesPresence(PackageInterface $package)
175
	{
176
		$this->binaryInstaller->installBinaries($package, $this->getInstallPath($package), false);
177
	}
178
179
	/**
180
	 * Returns the base path of the package without target-dir path
181
	 *
182
	 * It is used for BC as getInstallPath tends to be overridden by
183
	 * installer plugins but not getPackageBasePath
184
	 *
185
	 * @param  PackageInterface $package
186
	 * @return string
187
	 */
188
	protected function getPackageBasePath(PackageInterface $package)
189
	{
190
		$installPath = $this->getInstallPath($package);
191
		$targetDir = $package->getTargetDir();
192
		if ($targetDir) {
193
			return preg_replace('{/*'.str_replace('/', '/+', preg_quote($targetDir)).'/?$}', '', $installPath);
194
		}
195
		return $installPath;
196
	}
197
198
	/**
199
	 * @param \Composer\Package\PackageInterface $package
200
	 */
201
	protected function installCode(PackageInterface $package)
202
	{
203
		$downloadPath = $this->getInstallPath($package);
204
		$this->downloadManager->download($package, $downloadPath);
205
	}
206
207
	/**
208
	 * @param \Composer\Package\PackageInterface $initial
209
	 * @param \Composer\Package\PackageInterface $target
210
	 */
211
	protected function updateCode(PackageInterface $initial, PackageInterface $target)
212
	{
213
		$initialDownloadPath = $this->getInstallPath($initial);
214
		$targetDownloadPath = $this->getInstallPath($target);
215
		if ($targetDownloadPath !== $initialDownloadPath) {
216
			// if the target and initial dirs intersect, we force a remove + install
217
			// to avoid the rename wiping the target dir as part of the initial dir cleanup
218
			if (mb_substr($initialDownloadPath, 0, mb_strlen($targetDownloadPath)) === $targetDownloadPath
219
				|| mb_substr($targetDownloadPath, 0, mb_strlen($initialDownloadPath)) === $initialDownloadPath
220
			) {
221
				$this->removeCode($initial);
222
				$this->installCode($target);
223
				return;
224
			}
225
			$this->filesystem->rename($initialDownloadPath, $targetDownloadPath);
226
		}
227
		$this->downloadManager->update($initial, $target, $targetDownloadPath);
228
	}
229
230
	/**
231
	 * @param \Composer\Package\PackageInterface $package
232
	 */
233
	protected function removeCode(PackageInterface $package)
234
	{
235
		$downloadPath = $this->getPackageBasePath($package);
236
		$this->downloadManager->remove($package, $downloadPath);
237
	}
238
239
	protected function initializeVendorDir()
240
	{
241
		$this->filesystem->ensureDirectoryExists($this->vendorDir);
242
		$this->vendorDir = realpath($this->vendorDir);
0 ignored issues
show
Bug Best Practice introduced by
The property vendorDir does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
243
	}
244
245
	protected function initializeTemplateDir()
246
	{
247
		$this->filesystem->ensureDirectoryExists($this->templateDir);
248
		$this->templateDir = realpath($this->templateDir);
249
	}
250
}
251