Skip to content

Commit df31c63

Browse files
Merge remote-tracking branch '29355/implement-command-loader' into comprs_nov
2 parents 88660e7 + 7d4d669 commit df31c63

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+796
-355
lines changed

app/code/Magento/Backend/Console/Command/MaintenanceAllowIpsCommand.php

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2015 Adobe
4+
* All Rights Reserved.
55
*/
66
namespace Magento\Backend\Console\Command;
77

@@ -22,9 +22,10 @@ class MaintenanceAllowIpsCommand extends AbstractSetupCommand
2222
/**
2323
* Names of input arguments or options
2424
*/
25-
const INPUT_KEY_IP = 'ip';
26-
const INPUT_KEY_NONE = 'none';
27-
const INPUT_KEY_ADD = 'add';
25+
public const INPUT_KEY_IP = 'ip';
26+
public const INPUT_KEY_NONE = 'none';
27+
public const INPUT_KEY_ADD = 'add';
28+
public const NAME = 'maintenance:allow-ips';
2829

2930
/**
3031
* @var MaintenanceMode
@@ -76,7 +77,7 @@ protected function configure(): void
7677
'Add the IP address to existing list'
7778
),
7879
];
79-
$this->setName('maintenance:allow-ips')
80+
$this->setName(self::NAME)
8081
->setDescription('Sets maintenance mode exempt IPs')
8182
->setDefinition(array_merge($arguments, $options));
8283

app/code/Magento/Backend/Console/Command/MaintenanceDisableCommand.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2015 Adobe
4+
* All Rights Reserved.
55
*/
66
namespace Magento\Backend\Console\Command;
77

@@ -10,14 +10,16 @@
1010
*/
1111
class MaintenanceDisableCommand extends AbstractMaintenanceCommand
1212
{
13+
public const NAME = 'maintenance:disable';
14+
1315
/**
1416
* Initialization of the command
1517
*
1618
* @return void
1719
*/
1820
protected function configure()
1921
{
20-
$this->setName('maintenance:disable')->setDescription('Disables maintenance mode');
22+
$this->setName(self::NAME)->setDescription('Disables maintenance mode');
2123

2224
parent::configure();
2325
}

app/code/Magento/Backend/Console/Command/MaintenanceEnableCommand.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2015 Adobe
4+
* All Rights Reserved.
55
*/
66
namespace Magento\Backend\Console\Command;
77

@@ -10,14 +10,16 @@
1010
*/
1111
class MaintenanceEnableCommand extends AbstractMaintenanceCommand
1212
{
13+
public const NAME = 'maintenance:enable';
14+
1315
/**
1416
* Initialization of the command
1517
*
1618
* @return void
1719
*/
1820
protected function configure(): void
1921
{
20-
$this->setName('maintenance:enable')->setDescription('Enables maintenance mode');
22+
$this->setName(self::NAME)->setDescription('Enables maintenance mode');
2123

2224
parent::configure();
2325
}

app/code/Magento/Backend/Console/Command/MaintenanceStatusCommand.php

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2015 Adobe
4+
* All Rights Reserved.
55
*/
66
namespace Magento\Backend\Console\Command;
77

@@ -16,6 +16,8 @@
1616
*/
1717
class MaintenanceStatusCommand extends AbstractSetupCommand
1818
{
19+
public const NAME = 'maintenance:status';
20+
1921
/**
2022
* @var MaintenanceMode $maintenanceMode
2123
*/
@@ -40,7 +42,7 @@ public function __construct(MaintenanceMode $maintenanceMode)
4042
*/
4143
protected function configure(): void
4244
{
43-
$this->setName('maintenance:status')
45+
$this->setName(self::NAME)
4446
->setDescription('Displays maintenance mode status');
4547

4648
parent::configure();

dev/tests/static/testsuite/Magento/Test/Integrity/Library/DependencyTest.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2013 Adobe
4+
* All Rights Reserved.
55
*/
66
namespace Magento\Test\Integrity\Library;
77

@@ -40,7 +40,7 @@ protected function getAllowedNamespaces()
4040
'Framework',
4141
'SomeModule',
4242
'ModuleName',
43-
'Setup\Console\CommandList',
43+
'Setup\Console\CommandLoader',
4444
'Setup\Console\CompilerPreparation',
4545
'Setup\Model\ObjectManagerProvider',
4646
'Setup\Mvc\Bootstrap\InitParamListener',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php
2+
/**
3+
* Copyright 2021 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Framework\App\Test\Unit\Console\CommandLoader;
9+
10+
use Magento\Framework\Console\CommandLoader\Aggregate;
11+
use PHPUnit\Framework\MockObject\MockObject;
12+
use PHPUnit\Framework\TestCase;
13+
use Symfony\Component\Console\Command\Command;
14+
use Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
15+
use Symfony\Component\Console\Exception\CommandNotFoundException;
16+
17+
/**
18+
* Tests the "aggregate" command loader
19+
* @see Aggregate
20+
*/
21+
class AggregateTest extends TestCase
22+
{
23+
/** @var CommandLoaderInterface|MockObject */
24+
private MockObject|CommandLoaderInterface $firstMockCommandLoader;
25+
26+
/** @var CommandLoaderInterface|MockObject */
27+
private MockObject|CommandLoaderInterface $secondMockCommandLoader;
28+
29+
/** @var Aggregate */
30+
private Aggregate $aggregateCommandLoader;
31+
32+
protected function setUp(): void
33+
{
34+
$this->firstMockCommandLoader = $this->getMockBuilder(CommandLoaderInterface::class)->getMock();
35+
$this->secondMockCommandLoader = $this->getMockBuilder(CommandLoaderInterface::class)->getMock();
36+
$this->aggregateCommandLoader = new Aggregate([$this->firstMockCommandLoader, $this->secondMockCommandLoader]);
37+
}
38+
39+
/**
40+
* Test the various cases of `has` for the aggregate command loader:
41+
* - When at least one "internal" command loader has a command, the aggregate does as well
42+
* - When none of the "internal" command loaders has a command, neither does the aggregate
43+
*
44+
* @dataProvider provideTestCasesForHas
45+
*/
46+
public function testHas(bool $firstResult, bool $secondResult, bool $overallResult): void
47+
{
48+
$this->firstMockCommandLoader->method('has')->with('foo')->willReturn($firstResult);
49+
$this->secondMockCommandLoader->method('has')->with('foo')->willReturn($secondResult);
50+
51+
$this->assertEquals($overallResult, $this->aggregateCommandLoader->has('foo'));
52+
}
53+
54+
public function provideTestCasesForHas(): array
55+
{
56+
return [
57+
[true, false, true],
58+
[false, true, true],
59+
[false, false, false]
60+
];
61+
}
62+
63+
/**
64+
* Test the various cases of `get` for the aggregate command loader. Similar to `has`,
65+
* the return value of `Aggregate::get` mirrors its internal command loaders.
66+
*
67+
* For simplicity, this test does not cover the "no results" case. @see testGetThrow
68+
*
69+
* @dataProvider provideTestCasesForGet
70+
*/
71+
public function testGet(?Command $firstCmd, ?Command $secondCmd): void
72+
{
73+
$firstHas = (bool)$firstCmd;
74+
$secondHas = (bool)$secondCmd;
75+
76+
$this->firstMockCommandLoader->method('has')->with('foo')->willReturn($firstHas);
77+
if ($firstHas) {
78+
$this->firstMockCommandLoader->method('get')->with('foo')->willReturn($firstCmd);
79+
}
80+
81+
$this->secondMockCommandLoader->method('has')->with('foo')->willReturn($secondHas);
82+
if ($secondHas) {
83+
$this->secondMockCommandLoader->method('get')->with('foo')->willReturn($secondCmd);
84+
}
85+
86+
$this->assertInstanceOf(Command::class, $this->aggregateCommandLoader->get('foo'));
87+
}
88+
89+
public function provideTestCasesForGet(): array
90+
{
91+
return [
92+
[
93+
new Command(),
94+
null
95+
],
96+
[
97+
null,
98+
new Command()
99+
]
100+
];
101+
}
102+
103+
/**
104+
* When none of the internal command loaders have matching commands, the aggregate command loader
105+
* will throw an exception. @see CommandNotFoundException
106+
*/
107+
public function testGetThrow(): void
108+
{
109+
$this->firstMockCommandLoader->method('has')->with('foo')->willReturn(false);
110+
$this->secondMockCommandLoader->method('has')->with('foo')->willReturn(false);
111+
112+
$this->expectException(CommandNotFoundException::class);
113+
$this->aggregateCommandLoader->get('foo');
114+
}
115+
116+
/**
117+
* An aggregate command loader's `getNames` method returns the merged array of the `getNames`
118+
* return values of all its internal command loaders
119+
*/
120+
public function testGetNames(): void
121+
{
122+
$this->firstMockCommandLoader->method('getNames')->willReturn(['foo', 'bar']);
123+
$this->secondMockCommandLoader->method('getNames')->willReturn(['baz', 'qux']);
124+
125+
$this->assertEquals(['foo', 'bar', 'baz', 'qux'], $this->aggregateCommandLoader->getNames());
126+
}
127+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
<?php
2+
/**
3+
* Copyright 2021 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Framework\App\Test\Unit\Console;
9+
10+
use Magento\Framework\Console\CommandLoader;
11+
use Magento\Framework\ObjectManagerInterface;
12+
use PHPUnit\Framework\MockObject\MockObject;
13+
use PHPUnit\Framework\TestCase;
14+
use Symfony\Component\Console\Command\Command;
15+
use Symfony\Component\Console\Exception\CommandNotFoundException;
16+
17+
class CommandLoaderTest extends TestCase
18+
{
19+
/** @var MockObject|ObjectManagerInterface */
20+
private ObjectManagerInterface|MockObject $objectManagerMock;
21+
22+
protected function setUp(): void
23+
{
24+
$this->objectManagerMock = $this->getMockBuilder(ObjectManagerInterface::class)->getMock();
25+
}
26+
27+
/**
28+
* Test that the command loader, when provided zero commands, does not have a command named "foo"
29+
*/
30+
public function testHasWithZeroCommands(): void
31+
{
32+
$subj = new CommandLoader($this->objectManagerMock, []);
33+
34+
$this->assertFalse($subj->has('foo'));
35+
}
36+
37+
/**
38+
* Test that the command loader will return true when provided with a command "foo"
39+
*/
40+
public function testHasWithAtLeastOneCommand(): void
41+
{
42+
$subj = new CommandLoader($this->objectManagerMock, [
43+
[
44+
'name' => 'foo',
45+
'class' => FooCommand::class
46+
]
47+
]);
48+
49+
$this->assertTrue($subj->has('foo'));
50+
}
51+
52+
/**
53+
* Test that the command loader will throw a CommandNotFoundException when it does not have the requested command
54+
*/
55+
public function testGetWithZeroCommands(): void
56+
{
57+
$subj = new CommandLoader($this->objectManagerMock, []);
58+
59+
$this->expectException(CommandNotFoundException::class);
60+
61+
$subj->get('foo');
62+
}
63+
64+
/**
65+
* Test that the command loader returns a command when one it has is requested
66+
*/
67+
public function testGetWithAtLeastOneCommand(): void
68+
{
69+
$this->objectManagerMock
70+
->method('create')
71+
->with(FooCommand::class)
72+
->willReturn(new FooCommand());
73+
74+
$subj = new CommandLoader($this->objectManagerMock, [
75+
[
76+
'name' => 'foo',
77+
'class' => FooCommand::class
78+
]
79+
]);
80+
81+
$this->assertInstanceOf(FooCommand::class, $subj->get('foo'));
82+
}
83+
84+
/**
85+
* Test that the command loader will return an empty "names" array when it has none
86+
*/
87+
public function testGetNamesWithZeroCommands(): void
88+
{
89+
$subj = new CommandLoader($this->objectManagerMock, []);
90+
91+
$this->assertEquals([], $subj->getNames());
92+
}
93+
94+
/**
95+
* Test that the command loader returns an array of its command names when `getNames` is called
96+
*/
97+
public function testGetNames(): void
98+
{
99+
$subj = new CommandLoader($this->objectManagerMock, [
100+
[
101+
'name' => 'foo',
102+
'class' => FooCommand::class
103+
],
104+
[
105+
'name' => 'bar',
106+
'class' => 'BarCommand'
107+
]
108+
]);
109+
110+
$this->assertEquals(['foo', 'bar'], $subj->getNames());
111+
}
112+
}
113+
114+
// phpcs:ignore PSR1.Classes.ClassDeclaration
115+
class FooCommand extends Command
116+
{
117+
}

0 commit comments

Comments
 (0)