Completed
Push — master ( 550846...8c8483 )
by Anton
09:53
created

ControllerCommand::execute()   B

Complexity

Conditions 3
Paths 19

Size

Total Lines 37
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 37
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 21
nc 19
nop 2
1
<?php
2
/**
3
 * @copyright Bluz PHP Team
4
 * @link https://github.com/bluzphp/bluzman
5
 */
6
7
namespace Bluzman\Command\Generate;
8
9
use Bluzman\Generator;
10
use Bluzman\Input\InputException;
11
use Symfony\Component\Console\Input\ArrayInput;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Output\OutputInterface;
14
15
/**
16
 * ControllerCommand
17
 *
18
 * @package  Bluzman\Command
19
 */
20
class ControllerCommand extends AbstractGenerateCommand
21
{
22
    /**
23
     * Command configuration
24
     */
25
    protected function configure()
26
    {
27
        $this
28
            // the name of the command (the part after "bin/bluzman")
29
            ->setName('generate:controller')
30
            // the short description shown while running "php bin/bluzman list"
31
            ->setDescription('Generate a new controller')
32
            // the full command description shown when running the command with
33
            // the "--help" option
34
            ->setHelp('This command allows you to generate controller files')
35
        ;
36
37
        $this
38
            ->addModuleArgument()
39
            ->addControllerArgument()
40
        ;
41
    }
42
43
    /**
44
     * @param InputInterface $input
45
     * @param OutputInterface $output
46
     * @return void
47
     */
48
    protected function execute(InputInterface $input, OutputInterface $output)
49
    {
50
        try {
51
            $this->write("Running <info>generate:controller</info> command");
52
53
            $module = $input->getArgument('module');
54
            $this->getDefinition()->getArgument('module')->validate($module);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Symfony\Component\Console\Input\InputArgument as the method validate() does only exist in the following sub-classes of Symfony\Component\Console\Input\InputArgument: Bluzman\Input\InputArgument. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
55
56
            if (!$this->getApplication()->isModuleExists($module)) {
57
                $command = $this->getApplication()->find('generate:module');
58
59
                $arguments = [
60
                    'command' => 'generate:module',
61
                    'module' => $module
62
                ];
63
64
                $greetInput = new ArrayInput($arguments);
65
                $command->run($greetInput, $output);
66
            }
67
68
            $controller = $input->getArgument('controller');
69
            $this->getDefinition()->getArgument('controller')->validate($controller);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Symfony\Component\Console\Input\InputArgument as the method validate() does only exist in the following sub-classes of Symfony\Component\Console\Input\InputArgument: Bluzman\Input\InputArgument. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
70
71
            // generate directories and files
72
            $this->generate($input, $output);
73
74
            // verify it
75
            $this->verify($input, $output);
76
77
            $this->write(
78
                "Controller <info>{$controller}</info> has been successfully created " .
79
                "in the module <info>{$controller}</info>."
80
            );
81
        } catch (\Exception $e) {
82
            $this->error("ERROR: {$e->getMessage()}");
83
        }
84
    }
85
86
    /**
87
     * @param InputInterface $input
88
     * @param OutputInterface $output
89
     * @return $this
90
     */
91
    protected function generate(InputInterface $input, OutputInterface $output)
0 ignored issues
show
Unused Code introduced by
The parameter $output is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
92
    {
93
        $module = $input->getArgument('module');
94
        $controller = $input->getArgument('controller');
95
96
        $controllerFile = $this->getControllerPath($module, $controller);
97
        if (file_exists($controllerFile)) {
98
            $this->comment("Controller file <info>$module/$controller</info> already exists");
99
        } else {
100
            $template = new Generator\Template\ControllerTemplate;
101
            $template->setFilePath($controllerFile);
102
103
            $generator = new Generator\Generator($template);
104
            $generator->make();
105
        }
106
107
        $viewFile = $this->getViewPath($module, $controller);
108
        if (file_exists($viewFile)) {
109
            $this->comment("View file <info>$module/$controller</info> already exists");
110
        } else {
111
            $template = new Generator\Template\ViewTemplate;
112
            $template->setFilePath($viewFile);
113
            $template->setTemplateData(['name' => $controller]);
114
115
            $generator = new Generator\Generator($template);
116
            $generator->make();
117
        }
118
119
        return $this;
120
    }
121
122
    /**
123
     * @param InputInterface $input
124
     * @param OutputInterface $output
125
     * @return void
126
     * @throws \Bluzman\Generator\GeneratorException
127
     */
128
    public function verify(InputInterface $input, OutputInterface $output)
129
    {
130
        $modulePath = $this->getApplication()->getModulePath($input->getArgument('module'));
131
132
        $paths = [
133
            $modulePath,
134
            $modulePath . DS . 'controllers',
135
            $modulePath . DS . 'controllers' . DS . $input->getArgument('controller') . '.php',
136
            $modulePath . DS . 'views',
137
            $modulePath . DS . 'views' . DS . $input->getArgument('controller') . '.phtml',
138
139
        ];
140
141
        foreach ($paths as $path) {
142
            if (!$this->getFs()->exists($path)) {
143
                throw new Generator\GeneratorException("File or directory `$path` is not exists");
144
            }
145
        }
146
    }
147
}
148