Completed
Push — symfony3-wololo ( 50a832...8a87df )
by Kamil
18:56
created

InstallerContext::iDoNotProvideSurname()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
nc 1
cc 1
eloc 2
nop 0
1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Sylius\Behat\Context\Cli;
13
14
use Behat\Behat\Context\Context;
15
use Sylius\Bundle\CoreBundle\Command\InstallSampleDataCommand;
16
use Sylius\Bundle\CoreBundle\Command\SetupCommand;
17
use Symfony\Bundle\FrameworkBundle\Console\Application;
18
use Symfony\Component\Console\Helper\QuestionHelper;
19
use Symfony\Component\Console\Tester\CommandTester;
20
use Symfony\Component\HttpKernel\KernelInterface;
21
use Webmozart\Assert\Assert;
22
23
/**
24
 * @author Magdalena Banasiak <[email protected]>
25
 */
26
final class InstallerContext implements Context
27
{
28
    /**
29
     * @var KernelInterface
30
     */
31
    private $kernel;
32
33
    /**
34
     * @var Application
35
     */
36
    private $application;
37
38
    /**
39
     * @var CommandTester
40
     */
41
    private $tester;
42
43
    /**
44
     * @var QuestionHelper
45
     */
46
    private $questionHelper;
47
48
    /**
49
     * @var SetupCommand
50
     */
51
    private $command;
52
53
    /**
54
     * @var array
55
     */
56
    private $inputChoices = [
57
        'e-mail' => '[email protected]',
58
        'password' => 'pswd',
59
        'confirmation' => 'pswd',
60
    ];
61
62
    /**
63
     * @param KernelInterface $kernel
64
     */
65
    public function __construct(KernelInterface $kernel)
66
    {
67
        $this->kernel = $kernel;
68
    }
69
70
    /**
71
     * @When I run Sylius CLI installer
72
     */
73
    public function iRunSyliusCommandLineInstaller()
74
    {
75
        $this->application = new Application($this->kernel);
76
        $this->application->add(new SetupCommand());
77
78
        $this->command = $this->application->find('sylius:install:setup');
79
        $this->tester = new CommandTester($this->command);
80
81
        $this->iExecuteCommandWithInputChoices('sylius:install:setup');
82
    }
83
84
    /**
85
     * @Given I run Sylius Install Load Sample Data command
86
     */
87
    public function iRunSyliusInstallSampleDataCommand()
88
    {
89
        $this->application = new Application($this->kernel);
90
        $this->application->add(new InstallSampleDataCommand());
91
        $this->command = $this->application->find('sylius:install:sample-data');
92
        $this->tester = new CommandTester($this->command);
93
    }
94
95
    /**
96
     * @Given I confirm loading sample data
97
     */
98
    public function iConfirmLoadingData()
99
    {
100
        $this->iExecuteCommandAndConfirm('sylius:install:sample-data');
101
    }
102
103
    /**
104
     * @Then the command should finish successfully
105
     */
106
    public function commandSuccess()
107
    {
108
        Assert::same($this->tester->getStatusCode(), 0);
109
    }
110
111
    /**
112
     * @Then I should see output :text
113
     */
114
    public function iShouldSeeOutput($text)
115
    {
116
        Assert::contains($this->tester->getDisplay(), $text);
117
    }
118
119
    /**
120
     * @Given I do not provide an email
121
     */
122
    public function iDoNotProvideEmail()
123
    {
124
        $this->inputChoices['e-mail'] = '';
125
    }
126
127
    /**
128
     * @Given I do not provide a correct email
129
     */
130
    public function iDoNotProvideCorrectEmail()
131
    {
132
        $this->inputChoices['e-mail'] = 'janusz';
133
    }
134
135
    /**
136
     * @Given I provide full administrator data
137
     */
138
    public function iProvideFullAdministratorData()
139
    {
140
        $this->inputChoices['name'] = 'AdminName';
141
        $this->inputChoices['surname'] = 'AdminSurname';
142
        $this->inputChoices['e-mail'] = '[email protected]';
143
        $this->inputChoices['password'] = 'pswd1$';
144
        $this->inputChoices['confirmation'] = $this->inputChoices['password'];
145
        $this->inputChoices['localeCode'] = 'en_US';
146
    }
147
148
    /**
149
     * @param string $input
150
     *
151
     * @return resource
152
     */
153
    protected function getInputStream($input)
154
    {
155
        $stream = fopen('php://memory', 'r+', false);
156
        fwrite($stream, $input);
157
        rewind($stream);
158
159
        return $stream;
160
    }
161
162
    /**
163
     * @param string $name
164
     */
165
    private function iExecuteCommandWithInputChoices($name)
166
    {
167
        $this->questionHelper = $this->command->getHelper('question');
168
        $inputString = implode(PHP_EOL, $this->inputChoices);
169
        $this->questionHelper->setInputStream($this->getInputStream($inputString.PHP_EOL));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Symfony\Component\Console\Helper\HelperInterface as the method setInputStream() does only exist in the following implementations of said interface: Symfony\Component\Console\Helper\QuestionHelper, Symfony\Component\Consol...r\SymfonyQuestionHelper.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
170
171
        $this->tester->execute(['command' => $name]);
172
    }
173
174
    /**
175
     * @param string $name
176
     */
177
    private function iExecuteCommandAndConfirm($name)
178
    {
179
        $this->questionHelper = $this->command->getHelper('question');
180
        $inputString = 'y'.PHP_EOL;
181
        $this->questionHelper->setInputStream($this->getInputStream($inputString));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Symfony\Component\Console\Helper\HelperInterface as the method setInputStream() does only exist in the following implementations of said interface: Symfony\Component\Console\Helper\QuestionHelper, Symfony\Component\Consol...r\SymfonyQuestionHelper.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
182
183
        $this->tester->execute(['command' => $name]);
184
    }
185
}
186