Completed
Push — master ( e6b8db...c0bc47 )
by Christian
03:22
created

CreateCommand::execute()   D

Complexity

Conditions 11
Paths 257

Size

Total Lines 85

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 85
rs 4.9439
c 0
b 0
f 0
cc 11
nc 257
nop 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace N98\Magento\Command\Customer;
4
5
use Magento\Customer\Api\AccountManagementInterface;
6
use Magento\Framework\App\State\Proxy as AppState;
7
use Magento\Framework\Exception\LocalizedException;
8
use N98\Util\Console\Helper\Table\Renderer\RendererFactory;
9
use Symfony\Component\Console\Input\InputArgument;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Input\InputOption;
12
use Symfony\Component\Console\Output\OutputInterface;
13
14
class CreateCommand extends AbstractCustomerCommand
15
{
16
    /**
17
     * @var AccountManagementInterface
18
     */
19
    private $accountManagement;
20
21
    /**
22
     * @var AppState
23
     */
24
    private $appState;
25
26
    protected function configure()
27
    {
28
        $this
29
            ->setName('customer:create')
30
            ->addArgument('email', InputArgument::OPTIONAL, 'Email')
31
            ->addArgument('password', InputArgument::OPTIONAL, 'Password')
32
            ->addArgument('firstname', InputArgument::OPTIONAL, 'Firstname')
33
            ->addArgument('lastname', InputArgument::OPTIONAL, 'Lastname')
34
            ->addArgument('website', InputArgument::OPTIONAL, 'Website')
35
            ->addOption(
36
                'format',
37
                null,
38
                InputOption::VALUE_OPTIONAL,
39
                'Output Format. One of [' . implode(',', RendererFactory::getFormats()) . ']'
40
            )
41
            ->setDescription('Creates a new customer/user for shop frontend.');
42
    }
43
44
    /**
45
     * @param AccountManagementInterface $accountManagement
46
     * @param AppState $appState
47
     */
48
    public function inject(
49
        AccountManagementInterface $accountManagement,
50
        AppState $appState
51
    ) {
52
        $this->accountManagement = $accountManagement;
53
        $this->appState = $appState;
54
    }
55
56
    /**
57
     * @param InputInterface $input
58
     * @param OutputInterface $output
59
     * @return int
60
     * @throws \Exception
61
     */
62
    protected function execute(InputInterface $input, OutputInterface $output)
63
    {
64
        $this->detectMagento($output, true);
65
        if (!$this->initMagento()) {
66
            return 1;
67
        }
68
69
        $dialog = $this->getHelperSet()->get('dialog');
70
71
        // Email
72
        $email = $this->getHelperSet()->get('parameter')->askEmail($input, $output);
73
74
        // Password
75
        if (($password = $input->getArgument('password')) == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $password = $input->getArgument('password') of type string|string[]|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
76
            $password = $dialog->askHiddenResponse($output, '<question>Password:</question>');
77
        }
78
79
        // Firstname
80
        if (($firstname = $input->getArgument('firstname')) == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $firstname = $input->getArgument('firstname') of type string|string[]|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
81
            $firstname = $dialog->ask($output, '<question>Firstname:</question>');
82
        }
83
84
        // Lastname
85
        if (($lastname = $input->getArgument('lastname')) == null) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $lastname = $input->getArgument('lastname') of type string|string[]|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
86
            $lastname = $dialog->ask($output, '<question>Lastname:</question>');
87
        }
88
89
        $website = $this->getHelperSet()->get('parameter')->askWebsite($input, $output);
90
91
        // create new customer
92
        $customer = $this->getCustomer();
93
        $customer->setWebsiteId($website->getId());
94
        $customer->loadByEmail($email);
95
96
        $outputPlain = $input->getOption('format') === null;
97
98
        $table = array();
99
        $isError = false;
100
101
        if (!$customer->getId()) {
102
            $customer->setWebsiteId($website->getId());
103
            $customer->setEmail($email);
104
            $customer->setFirstname($firstname);
105
            $customer->setLastname($lastname);
106
            $customer->setStoreId($website->getDefaultGroup()->getDefaultStore()->getId());
107
108
            try {
109
                $this->appState->setAreaCode('frontend');
110
                $this->appState->emulateAreaCode(
111
                    'frontend',
112
                    [$this, 'createCustomer'],
113
                    [$customer, $password]
114
                );
115
116
                if ($outputPlain) {
117
                    $output->writeln(
118
                        sprintf(
119
                            '<info>Customer <comment>%s</comment> successfully created</info>',
120
                            $email
121
                        )
122
                    );
123
                } else {
124
                    $table[] = array(
125
                        $email,
126
                        $password,
127
                        $firstname,
128
                        $lastname,
129
                    );
130
                }
131
            } catch (\Exception $e) {
132
                $isError = true;
133
                $output->writeln('<error>' . $e->getMessage() . '</error>');
134
            }
135
        } elseif ($outputPlain) {
136
            $output->writeln('<warning>Customer ' . $email . ' already exists</warning>');
137
        }
138
139
        if (!$outputPlain) {
140
            $this->getHelper('table')
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 setHeaders() does only exist in the following implementations of said interface: N98\Util\Console\Helper\TableHelper, Symfony\Component\Console\Helper\TableHelper.

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...
141
                ->setHeaders(array('email', 'password', 'firstname', 'lastname'))
142
                ->renderByFormat($output, $table, $input->getOption('format'));
143
        }
144
145
        return $isError ? 1 : 0;
146
    }
147
148
    /**
149
     * @param string $customer
150
     * @param string $password
151
     * @throws \Magento\Framework\Exception\LocalizedException
152
     */
153
    public function createCustomer($customer, $password)
154
    {
155
        try {
156
            // Fix for proxy which does not respect "emulateAreaCode".
157
158
            // @see \Magento\Framework\Session\SessionManager::isSessionExists Hack to prevent session problems
159
            @session_start();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
160
161
            /** @var \Magento\Theme\Model\View\Design $design */
162
            $design = $this->getObjectManager()->get(\Magento\Theme\Model\View\Design::class);
163
            $design->setArea('frontend');
164
            $this->accountManagement->createAccount(
165
                $customer->getDataModel(),
0 ignored issues
show
Bug introduced by
The method getDataModel cannot be called on $customer (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
166
                $password
167
            );
168
        } catch (LocalizedException $e) {
0 ignored issues
show
Bug introduced by
The class Magento\Framework\Exception\LocalizedException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
169
            if ($e->getRawMessage() !== 'Design config must have area and store.') {
170
                throw $e;
171
            }
172
        }
173
    }
174
}
175