Skip to content

Commit 5d2f685

Browse files
authored
Merge pull request #7405 from magento-arcticfoxes/B2B-2148
B2B-2148: Can no longer install when my database name has a dash in it
2 parents 67fbf08 + eb3a969 commit 5d2f685

File tree

4 files changed

+118
-13
lines changed

4 files changed

+118
-13
lines changed

lib/internal/Magento/Framework/App/Router/ActionList.php

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@
1010
use Magento\Framework\App\Filesystem\DirectoryList;
1111
use Magento\Framework\App\ObjectManager;
1212
use Magento\Framework\App\State;
13+
use Magento\Framework\App\Utility\ReflectionClassFactory;
1314
use Magento\Framework\Config\CacheInterface;
15+
use Magento\Framework\Exception\FileSystemException;
1416
use Magento\Framework\Module\Dir\Reader as ModuleReader;
1517
use Magento\Framework\Serialize\Serializer\Serialize;
1618
use Magento\Framework\Serialize\SerializerInterface;
19+
use ReflectionClass;
20+
use ReflectionException;
1721

1822
/**
1923
* Class to retrieve action class.
@@ -23,7 +27,7 @@ class ActionList
2327
/**
2428
* Not allowed string in route's action path to avoid disclosing admin url
2529
*/
26-
const NOT_ALLOWED_IN_NAMESPACE_PATH = 'adminhtml';
30+
public const NOT_ALLOWED_IN_NAMESPACE_PATH = 'adminhtml';
2731

2832
/**
2933
* List of application actions
@@ -55,30 +59,43 @@ class ActionList
5559
*/
5660
private $actionInterface;
5761

62+
/**
63+
* @var ReflectionClassFactory|null
64+
*/
65+
private $reflectionClassFactory;
66+
5867
/**
5968
* @param CacheInterface $cache
6069
* @param ModuleReader $moduleReader
6170
* @param string $actionInterface
6271
* @param string $cacheKey
6372
* @param array $reservedWords
6473
* @param SerializerInterface|null $serializer
74+
* @param State|null $state
75+
* @param DirectoryList|null $directoryList
76+
* @param ReflectionClassFactory|null $reflectionClassFactory
77+
* @throws FileSystemException
6578
*/
6679
public function __construct(
6780
CacheInterface $cache,
6881
ModuleReader $moduleReader,
6982
$actionInterface = ActionInterface::class,
7083
$cacheKey = 'app_action_list',
7184
$reservedWords = [],
72-
SerializerInterface $serializer = null
85+
SerializerInterface $serializer = null,
86+
State $state = null,
87+
DirectoryList $directoryList = null,
88+
ReflectionClassFactory $reflectionClassFactory = null
7389
) {
7490
$this->reservedWords = array_merge($reservedWords, $this->reservedWords);
7591
$this->actionInterface = $actionInterface;
76-
$objectManager = ObjectManager::getInstance();
77-
$this->serializer = $serializer ?: $objectManager->get(Serialize::class);
78-
$state = $objectManager->get(State::class);
92+
$this->serializer = $serializer ?: ObjectManager::getInstance()->get(Serialize::class);
93+
$state = $state ?: ObjectManager::getInstance()->get(State::class);
94+
$this->reflectionClassFactory = $reflectionClassFactory
95+
?: ObjectManager::getInstance()->get(ReflectionClassFactory::class);
7996

8097
if ($state->getMode() === State::MODE_PRODUCTION) {
81-
$directoryList = $objectManager->get(DirectoryList::class);
98+
$directoryList = $directoryList ?: ObjectManager::getInstance()->get(DirectoryList::class);
8299
$file = $directoryList->getPath(DirectoryList::GENERATED_METADATA)
83100
. '/' . $cacheKey . '.' . 'php';
84101

@@ -106,6 +123,7 @@ public function __construct(
106123
* @param string $namespace
107124
* @param string $action
108125
* @return null|string
126+
* @throws ReflectionException
109127
*/
110128
public function get($module, $area, $namespace, $action)
111129
{
@@ -126,11 +144,35 @@ public function get($module, $area, $namespace, $action)
126144
$module . '\\controller' . $area . '\\' . $namespace . '\\' . $action
127145
)
128146
);
129-
if (isset($this->actions[$fullPath])) {
130-
return is_subclass_of($this->actions[$fullPath], $this->actionInterface)
131-
? $this->actions[$fullPath]
132-
: null;
147+
try {
148+
if ($this->validateActionClass($fullPath)) {
149+
return $this->actions[$fullPath];
150+
}
151+
} catch (ReflectionException $e) {
152+
return null;
133153
}
154+
134155
return null;
135156
}
157+
158+
/**
159+
* Validate Action Class
160+
*
161+
* @param string $fullPath
162+
* @return bool
163+
* @throws ReflectionException
164+
*/
165+
private function validateActionClass(string $fullPath): bool
166+
{
167+
if (isset($this->actions[$fullPath])) {
168+
if (!is_subclass_of($this->actions[$fullPath], $this->actionInterface)) {
169+
return false;
170+
}
171+
$reflectionClass = $this->reflectionClassFactory->create($this->actions[$fullPath]);
172+
if ($reflectionClass->isInstantiable()) {
173+
return true;
174+
}
175+
}
176+
return false;
177+
}
136178
}

lib/internal/Magento/Framework/App/Test/Unit/Router/ActionListTest.php

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99

1010
use Magento\Framework\App\ActionInterface;
1111
use Magento\Framework\App\Router\ActionList;
12+
use Magento\Framework\App\Utility\ReflectionClassFactory;
1213
use Magento\Framework\Config\CacheInterface;
1314
use Magento\Framework\Module\Dir\Reader;
1415
use Magento\Framework\Serialize\SerializerInterface;
1516
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
1617
use PHPUnit\Framework\MockObject\MockObject;
1718
use PHPUnit\Framework\TestCase;
19+
use ReflectionClass;
1820

1921
class ActionListTest extends TestCase
2022
{
@@ -43,12 +45,27 @@ class ActionListTest extends TestCase
4345
*/
4446
private $serializerMock;
4547

48+
/**
49+
* @var MockObject|ReflectionClass
50+
*/
51+
private $reflectionClass;
52+
53+
/**
54+
* @var ReflectionClassFactory|MockObject
55+
*/
56+
private $reflectionClassFactory;
57+
4658
protected function setUp(): void
4759
{
4860
$this->objectManager = new ObjectManager($this);
4961
$this->cacheMock = $this->getMockForAbstractClass(CacheInterface::class);
5062
$this->readerMock = $this->createMock(Reader::class);
5163
$this->serializerMock = $this->getMockForAbstractClass(SerializerInterface::class);
64+
$this->reflectionClass = $this->createStub(ReflectionClass::class);
65+
$this->reflectionClassFactory = $this->getMockBuilder(ReflectionClassFactory::class)
66+
->disableOriginalConstructor()
67+
->getMock();
68+
$this->reflectionClassFactory->method('create')->willReturn($this->reflectionClass);
5269
}
5370

5471
public function testConstructActionsCached()
@@ -89,8 +106,10 @@ public function testConstructActionsNoCached()
89106
* @param string|null $expected
90107
* @dataProvider getDataProvider
91108
*/
92-
public function testGet($module, $area, $namespace, $action, $data, $expected)
109+
public function testGet($module, $area, $namespace, $action, $data, $isInstantiable, $expected)
93110
{
111+
$this->reflectionClass->method('isInstantiable')->willReturn($isInstantiable);
112+
94113
$this->cacheMock->expects($this->once())
95114
->method('load')
96115
->willReturn(false);
@@ -100,7 +119,12 @@ public function testGet($module, $area, $namespace, $action, $data, $expected)
100119
->method('getActionFiles')
101120
->willReturn($data);
102121
$this->createActionListInstance();
103-
$this->assertEquals($expected, $this->actionList->get($module, $area, $namespace, $action));
122+
$this->assertEquals($expected, $this->actionList->get(
123+
$module,
124+
$area,
125+
$namespace,
126+
$action
127+
));
104128
}
105129

106130
/**
@@ -123,6 +147,7 @@ public function getDataProvider()
123147
'Namespace',
124148
'Index',
125149
['magento\module\controller\area\namespace\index' => $mockClassName],
150+
true,
126151
$actionClass
127152
],
128153
[
@@ -131,6 +156,7 @@ public function getDataProvider()
131156
'Namespace',
132157
'Index',
133158
['magento\module\controller\namespace\index' => $mockClassName],
159+
true,
134160
$actionClass
135161
],
136162
[
@@ -139,6 +165,7 @@ public function getDataProvider()
139165
'Namespace',
140166
'Catch',
141167
['magento\module\controller\area\namespace\catchaction' => $mockClassName],
168+
true,
142169
$actionClass
143170
],
144171
[
@@ -147,6 +174,7 @@ public function getDataProvider()
147174
'Namespace',
148175
'Index',
149176
['magento\module\controller\area\namespace\index' => 'Not_Exist_Class'],
177+
false,
150178
null
151179
],
152180
[
@@ -155,6 +183,7 @@ public function getDataProvider()
155183
'Namespace',
156184
'Index',
157185
[],
186+
false,
158187
null
159188
],
160189
[
@@ -163,6 +192,7 @@ public function getDataProvider()
163192
'adminhtml_product',
164193
'index',
165194
'magento\module\controller\adminhtml\product\index' => '$mockClassName',
195+
false,
166196
null
167197
],
168198
];
@@ -176,6 +206,7 @@ private function createActionListInstance()
176206
'cache' => $this->cacheMock,
177207
'moduleReader' => $this->readerMock,
178208
'serializer' => $this->serializerMock,
209+
'reflectionClassFactory' => $this->reflectionClassFactory
179210
]
180211
);
181212
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Magento\Framework\App\Utility;
10+
11+
use ReflectionClass;
12+
use ReflectionException;
13+
14+
/**
15+
* Factory for \ReflectionClass
16+
*/
17+
class ReflectionClassFactory
18+
{
19+
/**
20+
* Create a reflection class object
21+
*
22+
* @param object|string $objectOrClass
23+
*
24+
* @return ReflectionClass
25+
* @throws ReflectionException
26+
*/
27+
public function create($objectOrClass): ReflectionClass
28+
{
29+
return new ReflectionClass($objectOrClass);
30+
}
31+
}

setup/src/Magento/Setup/Validator/DbValidator.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,8 @@ public function checkDatabaseConnectionWithDriverOptions(
142142
private function checkDatabaseName(\Magento\Framework\DB\Adapter\AdapterInterface $connection, $dbName)
143143
{
144144
try {
145-
$connection->query("SHOW TABLES FROM $dbName")->fetchAll(\PDO::FETCH_COLUMN, 0);
145+
$query = sprintf("SHOW TABLES FROM `%s`", $dbName);
146+
$connection->query($query)->fetchAll(\PDO::FETCH_COLUMN, 0);
146147
return true;
147148
} catch (\Exception $e) {
148149
throw new \Magento\Setup\Exception(

0 commit comments

Comments
 (0)