Skip to content

Commit dc9657f

Browse files
committed
MAGETWO-37710: Setup wizard fails in readiness check when magento is deployed by composer create-project
- Create ComposerInformation class to handle gathering information from composer
1 parent 7b3a73a commit dc9657f

File tree

3 files changed

+146
-103
lines changed

3 files changed

+146
-103
lines changed

setup/src/Magento/Setup/Controller/Environment.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,18 @@
55
*/
66
namespace Magento\Setup\Controller;
77

8-
use Composer\Package\LinkConstraint\VersionConstraint;
98
use Composer\Package\Version\VersionParser;
109
use Zend\Mvc\Controller\AbstractActionController;
1110
use Zend\View\Model\JsonModel;
11+
use Magento\Setup\Model\ComposerInformation;
1212
use Magento\Setup\Model\PhpInformation;
1313
use Magento\Setup\Model\FilePermissions;
1414

15+
/**
16+
* Class Environment
17+
*
18+
* Provides information and checks about the environment.
19+
*/
1520
class Environment extends AbstractActionController
1621
{
1722
/**
@@ -34,15 +39,18 @@ class Environment extends AbstractActionController
3439
* @param PhpInformation $phpInformation
3540
* @param FilePermissions $permissions
3641
* @param VersionParser $versionParser
42+
* @param ComposerInformation $composerInformation
3743
*/
3844
public function __construct(
3945
PhpInformation $phpInformation,
4046
FilePermissions $permissions,
41-
VersionParser $versionParser
47+
VersionParser $versionParser,
48+
ComposerInformation $composerInformation
4249
) {
4350
$this->phpInformation = $phpInformation;
44-
$this->permissions = $permissions;
51+
$this->permissions = $permissions;
4552
$this->versionParser = $versionParser;
53+
$this->composerInformation = $composerInformation;
4654
}
4755

4856
/**
@@ -53,7 +61,7 @@ public function __construct(
5361
public function phpVersionAction()
5462
{
5563
try {
56-
$requiredVersion = $this->phpInformation->getRequiredPhpVersion();
64+
$requiredVersion = $this->composerInformation->getRequiredPhpVersion();
5765
} catch (\Exception $e) {
5866
return new JsonModel(
5967
[
@@ -123,7 +131,7 @@ public function phpSettingsAction()
123131
public function phpExtensionsAction()
124132
{
125133
try {
126-
$required = $this->phpInformation->getRequired();
134+
$required = $this->composerInformation->getRequiredExtensions();
127135
$current = $this->phpInformation->getCurrent();
128136

129137
} catch (\Exception $e) {
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
/**
3+
* Copyright © 2015 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Setup\Model;
8+
9+
use Composer\Factory as ComposerFactory;
10+
use Composer\IO\BufferIO;
11+
use Composer\Package\Link;
12+
use Composer\Package\PackageInterface;
13+
use Magento\Framework\Filesystem;
14+
15+
/**
16+
* Class ComposerInformation uses Composer to determine dependency information.
17+
*/
18+
class ComposerInformation
19+
{
20+
/**
21+
* @var \Composer\Composer
22+
*/
23+
private $composer;
24+
25+
/**
26+
* @var \Composer\Package\Locker
27+
*/
28+
private $locker;
29+
30+
/**
31+
* Constructor
32+
*
33+
* @param BufferIO $io
34+
*/
35+
public function __construct(
36+
BufferIO $io
37+
) {
38+
// composer.json will be in same directory as vendor
39+
$vendorDir = require BP . '/app/etc/vendor_path.php';
40+
$composerJson = realpath(BP . "/{$vendorDir}/../composer.json");
41+
42+
// Create Composer
43+
$this->composer = ComposerFactory::create($io, $composerJson);
44+
$this->locker = $this->composer->getLocker();
45+
}
46+
47+
/**
48+
* Retrieves required php version
49+
*
50+
* @return string
51+
* @throws \Exception If attributes are missing in composer.lock file.
52+
*/
53+
public function getRequiredPhpVersion()
54+
{
55+
if ($this->isMagentoRoot()) {
56+
$allPlatformReqs = $this->locker->getPlatformRequirements(true);
57+
$requiredPhpVersion = $allPlatformReqs['php']->getPrettyConstraint();
58+
} else {
59+
$packages = $this->locker->getLockedRepository()->getPackages();
60+
/** @var PackageInterface $package */
61+
foreach ($packages as $package) {
62+
if ($package instanceof PackageInterface) {
63+
$packageName = $package->getPrettyName();
64+
if ($packageName === 'magento/product-community-edition') {
65+
$phpRequirementLink = $package->getRequires()['php'];
66+
if ($phpRequirementLink instanceof Link) {
67+
$requiredPhpVersion = $phpRequirementLink->getPrettyConstraint();
68+
}
69+
}
70+
}
71+
}
72+
}
73+
74+
if (!isset($requiredPhpVersion)) {
75+
throw new \Exception('Cannot find php version requirement in \'composer.lock\' file');
76+
}
77+
return $requiredPhpVersion;
78+
}
79+
80+
/**
81+
* Retrieve list of required extensions
82+
*
83+
* Collect required extensions from composer.lock file
84+
*
85+
* @return array
86+
* @throws \Exception If attributes are missing in composer.lock file.
87+
*/
88+
public function getRequiredExtensions()
89+
{
90+
if ($this->isMagentoRoot()) {
91+
$allPlatformReqs = $this->locker->getPlatformRequirements(true);
92+
foreach ($allPlatformReqs as $reqIndex => $constraint) {
93+
if (substr($reqIndex, 0, 4) === 'ext-') {
94+
$requiredExtensions[] = substr($reqIndex, 4);
95+
}
96+
}
97+
} else {
98+
$requiredExtensions = [];
99+
100+
/** @var \Composer\Package\CompletePackage $package */
101+
foreach ($this->locker->getLockedRepository()->getPackages() as $package) {
102+
$requires = $package->getRequires();
103+
$requires = array_merge($requires, $package->getDevRequires());
104+
foreach ($requires as $reqIndex => $constraint) {
105+
if (substr($reqIndex, 0, 4) === 'ext-') {
106+
$requiredExtensions[] = substr($reqIndex, 4);
107+
}
108+
}
109+
}
110+
}
111+
112+
if (!isset($requiredExtensions)) {
113+
throw new \Exception('Cannot find extensions in \'composer.lock\' file');
114+
}
115+
return $requiredExtensions;
116+
}
117+
118+
/**
119+
* Determines if Magento is the root package or it is included as a requirement.
120+
*
121+
* @return bool
122+
*/
123+
private function isMagentoRoot()
124+
{
125+
$rootPackage = $this->composer->getPackage();
126+
return ('magento/magento2ce' == $rootPackage->getName());
127+
}
128+
}

setup/src/Magento/Setup/Model/PhpInformation.php

Lines changed: 5 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66

77
namespace Magento\Setup\Model;
88

9-
use Magento\Framework\App\Filesystem\DirectoryList;
109
use Magento\Framework\Filesystem;
1110

11+
/**
12+
* Class PhpInformation
13+
*
14+
* Provides information and checks about the current and required PHP settings.
15+
*/
1216
class PhpInformation
1317
{
1418

@@ -17,54 +21,13 @@ class PhpInformation
1721
*/
1822
const XDEBUG_NESTED_LEVEL = 200;
1923

20-
/**
21-
* List of required extensions
22-
*
23-
* @var array
24-
*/
25-
protected $required;
26-
2724
/**
2825
* List of currently installed extensions
2926
*
3027
* @var array
3128
*/
3229
protected $current = [];
3330

34-
/**
35-
* Interface to read composer.lock file
36-
*
37-
* @var \Magento\Framework\Filesystem\Directory\ReadInterface
38-
*/
39-
private $rootDir;
40-
41-
/**
42-
* Constructor
43-
*
44-
* @param Filesystem $filesystem
45-
*/
46-
public function __construct(
47-
Filesystem $filesystem
48-
) {
49-
$this->rootDir = $filesystem->getDirectoryRead(DirectoryList::ROOT);
50-
}
51-
52-
/**
53-
* Retrieves required php version
54-
*
55-
* @return string
56-
* @throws \Exception If attributes are missing in composer.lock file.
57-
*/
58-
public function getRequiredPhpVersion()
59-
{
60-
$composerInfo = $this->getComposerInfo();
61-
if (!empty($composerInfo['platform']['php'])) {
62-
return $composerInfo['platform']['php'];
63-
} else {
64-
throw new \Exception('Missing key \'platform=>php\' in \'composer.lock\' file');
65-
}
66-
}
67-
6831
/**
6932
* Returns minimum required XDebug nested level
7033
* @return int
@@ -74,62 +37,6 @@ public function getRequiredMinimumXDebugNestedLevel()
7437
return self::XDEBUG_NESTED_LEVEL;
7538
}
7639

77-
/**
78-
* Retrieve list of required extensions
79-
*
80-
* Collect required extensions from composer.lock file
81-
*
82-
* @return array
83-
* @throws \Exception If attributes are missing in composer.lock file.
84-
*/
85-
public function getRequired()
86-
{
87-
if (null === $this->required) {
88-
$composerInfo = $this->getComposerInfo();
89-
$declaredDependencies = [];
90-
91-
if (!empty($composerInfo['platform-dev'])) {
92-
$declaredDependencies = array_merge($declaredDependencies, array_keys($composerInfo['platform-dev']));
93-
} else {
94-
throw new \Exception('Missing key \'platform-dev\' in \'composer.lock\' file');
95-
}
96-
if (!empty($composerInfo['packages'])) {
97-
foreach ($composerInfo['packages'] as $package) {
98-
if (!empty($package['require'])) {
99-
$declaredDependencies = array_merge($declaredDependencies, array_keys($package['require']));
100-
}
101-
}
102-
} else {
103-
throw new \Exception('Missing key \'packages\' in \'composer.lock\' file');
104-
}
105-
if ($declaredDependencies) {
106-
$declaredDependencies = array_unique($declaredDependencies);
107-
$phpDependencies = [];
108-
foreach ($declaredDependencies as $dependency) {
109-
if (stripos($dependency, 'ext-') === 0) {
110-
$phpDependencies[] = substr($dependency, 4);
111-
}
112-
}
113-
$this->required = array_unique($phpDependencies);
114-
}
115-
}
116-
return $this->required;
117-
}
118-
119-
/**
120-
* Checks existence of composer.lock and returns its contents
121-
*
122-
* @return array
123-
* @throws \Exception
124-
*/
125-
private function getComposerInfo()
126-
{
127-
if (!$this->rootDir->isExist('composer.lock')) {
128-
throw new \Exception('Cannot read \'composer.lock\' file');
129-
}
130-
return json_decode($this->rootDir->readFile('composer.lock'), true);
131-
}
132-
13340
/**
13441
* Retrieve list of currently installed extensions
13542
*

0 commit comments

Comments
 (0)