TYPO3  7.6
ExtensionInstaller.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Composer\Installer;
3 
4 /***************************************************************
5  * Copyright notice
6  *
7  * (c) 2014 Thomas Maroschik <tmaroschik@dfau.de>
8  * All rights reserved
9  *
10  * This script is part of the TYPO3 project. The TYPO3 project is
11  * free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * The GNU General Public License can be found at
17  * http://www.gnu.org/copyleft/gpl.html.
18  *
19  * This script is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU General Public License for more details.
23  *
24  * This copyright notice MUST APPEAR in all copies of the script!
25  ***************************************************************/
26 
27 use Composer\Package\PackageInterface;
29 
35 class ExtensionInstaller implements \Composer\Installer\InstallerInterface {
36 
37  const TYPO3_EXT_DIR = 'ext';
38 
42  protected $extensionDir;
43 
47  protected $composer;
48 
52  protected $downloadManager;
53 
57  protected $filesystem;
58 
62  protected $pluginConfig;
63 
68  public function __construct(\Composer\Composer $composer, \Composer\Util\Filesystem $filesystem = NULL) {
69  $this->composer = $composer;
70  $this->downloadManager = $composer->getDownloadManager();
71 
72  $this->filesystem = $filesystem ? : new \Composer\Util\Filesystem();
73  $this->initializeConfiguration();
74  $this->initializeExtensionDir();
75  }
76 
80  protected function initializeConfiguration() {
81  $this->pluginConfig = Config::load($this->composer);
82  }
83 
87  protected function initializeExtensionDir() {
88  $configDir = $this->filesystem->normalizePath($this->pluginConfig->get('config-dir'));
89  $this->extensionDir = $configDir . DIRECTORY_SEPARATOR . self::TYPO3_EXT_DIR;
90  }
91 
98  public function supports($packageType) {
99  return $packageType !== 'typo3-cms-core'
100  // strncmp is about 20% faster than substr
101  && strncmp('typo3-cms-', $packageType, 10) === 0;
102  }
103 
112  public function isInstalled(\Composer\Repository\InstalledRepositoryInterface $repo, PackageInterface $package) {
113  return $repo->hasPackage($package) && is_readable($this->getInstallPath($package));
114  }
115 
122  public function install(\Composer\Repository\InstalledRepositoryInterface $repo, PackageInterface $package) {
123  $this->installCode($package);
124  if (!$repo->hasPackage($package)) {
125  $repo->addPackage(clone $package);
126  }
127  }
128 
138  public function update(\Composer\Repository\InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target) {
139  if (!$repo->hasPackage($initial)) {
140  throw new \InvalidArgumentException('Package is not installed: ' . $initial);
141  }
142  $this->updateCode($initial, $target);
143  $repo->removePackage($initial);
144  if (!$repo->hasPackage($target)) {
145  $repo->addPackage(clone $target);
146  }
147  }
148 
157  public function uninstall(\Composer\Repository\InstalledRepositoryInterface $repo, PackageInterface $package) {
158  if (!$repo->hasPackage($package)) {
159  throw new \InvalidArgumentException('Package is not installed: ' . $package);
160  }
161 
162  $this->removeCode($package);
163  $repo->removePackage($package);
164  }
165 
172  public function getInstallPath(PackageInterface $package) {
173  $extensionKey = '';
174  foreach ($package->getReplaces() as $packageName => $version) {
175  if (strpos($packageName, '/') === FALSE) {
176  $extensionKey = trim($packageName);
177  break;
178  }
179  }
180  if (empty($extensionKey)) {
181  list(, $extensionKey) = explode('/', $package->getName(), 2);
182  $extensionKey = str_replace('-', '_', $extensionKey);
183  }
184  return $this->extensionDir . DIRECTORY_SEPARATOR . $extensionKey;
185  }
186 
190  protected function installCode(PackageInterface $package) {
191  $this->downloadManager->download($package, $this->getInstallPath($package));
192  }
193 
198  protected function updateCode(PackageInterface $initial, PackageInterface $target) {
199  $initialDownloadPath = $this->getInstallPath($initial);
200  $targetDownloadPath = $this->getInstallPath($target);
201  if ($targetDownloadPath !== $initialDownloadPath) {
202  // if the target and initial dirs intersect, we force a remove + install
203  // to avoid the rename wiping the target dir as part of the initial dir cleanup
204  if (substr($initialDownloadPath, 0, strlen($targetDownloadPath)) === $targetDownloadPath
205  || substr($targetDownloadPath, 0, strlen($initialDownloadPath)) === $initialDownloadPath
206  ) {
207  $this->removeCode($initial);
208  $this->installCode($target);
209 
210  return;
211  }
212 
213  $this->filesystem->rename($initialDownloadPath, $targetDownloadPath);
214  }
215  $this->downloadManager->update($initial, $target, $targetDownloadPath);
216  }
217 
221  protected function removeCode(PackageInterface $package) {
222  $this->downloadManager->remove($package, $this->getInstallPath($package));
223  }
224 
225 }