Completed
Pull Request — master (#30)
by Anton
17:34
created

ControllerCommand   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 128
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 12

Test Coverage

Coverage 82.46%

Importance

Changes 0
Metric Value
wmc 10
lcom 2
cbo 12
dl 0
loc 128
ccs 47
cts 57
cp 0.8246
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 17 1
B execute() 0 37 3
B generate() 0 30 3
A verify() 0 19 3
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 Symfony\Component\Console\Input\ArrayInput;
11
use Symfony\Component\Console\Input\InputInterface;
12
use Symfony\Component\Console\Output\OutputInterface;
13
14
/**
15
 * ControllerCommand
16
 *
17
 * @package  Bluzman\Command\Generate
18
 */
19
class ControllerCommand extends AbstractGenerateCommand
20
{
21
    /**
22
     * Command configuration
23
     */
24 14
    protected function configure()
25
    {
26
        $this
27
            // the name of the command (the part after "bin/bluzman")
28 14
            ->setName('generate:controller')
29
            // the short description shown while running "php bin/bluzman list"
30 14
            ->setDescription('Generate a new controller')
31
            // the full command description shown when running the command with
32
            // the "--help" option
33 14
            ->setHelp('This command allows you to generate controller files')
34
        ;
35
36
        $this
37 14
            ->addModuleArgument()
38 14
            ->addControllerArgument()
39
        ;
40 14
    }
41
42
    /**
43
     * @param InputInterface $input
44
     * @param OutputInterface $output
45
     * @return void
46
     */
47 1
    protected function execute(InputInterface $input, OutputInterface $output)
48
    {
49
        try {
50 1
            $this->write("Running <info>generate:controller</info> command");
51
52 1
            $module = $input->getArgument('module');
53 1
            $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...
54
55 1
            if (!$this->getApplication()->isModuleExists($module)) {
56
                $command = $this->getApplication()->find('generate:module');
57
58
                $arguments = [
59
                    'command' => 'generate:module',
60
                    'module' => $module
61
                ];
62
63
                $greetInput = new ArrayInput($arguments);
64
                $command->run($greetInput, $output);
65
            }
66
67 1
            $controller = $input->getArgument('controller');
68 1
            $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...
69
70
            // generate directories and files
71 1
            $this->generate($input, $output);
72
73
            // verify it
74 1
            $this->verify($input, $output);
75
76 1
            $this->write(
77 1
                "Controller <info>{$controller}</info> has been successfully created " .
78 1
                "in the module <info>{$controller}</info>."
79
            );
80
        } catch (\Exception $e) {
81
            $this->error("ERROR: {$e->getMessage()}");
82
        }
83 1
    }
84
85
    /**
86
     * @param InputInterface $input
87
     * @param OutputInterface $output
88
     * @return $this
89
     */
90 1
    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...
91
    {
92 1
        $module = $input->getArgument('module');
93 1
        $controller = $input->getArgument('controller');
94
95 1
        $controllerFile = $this->getControllerPath($module, $controller);
96 1
        if (file_exists($controllerFile)) {
97
            $this->comment("Controller file <info>$module/$controller</info> already exists");
98
        } else {
99 1
            $template = new Generator\Template\ControllerTemplate;
100 1
            $template->setFilePath($controllerFile);
101
102 1
            $generator = new Generator\Generator($template);
103 1
            $generator->make();
104
        }
105
106 1
        $viewFile = $this->getViewPath($module, $controller);
107 1
        if (file_exists($viewFile)) {
108
            $this->comment("View file <info>$module/$controller</info> already exists");
109
        } else {
110 1
            $template = new Generator\Template\ViewTemplate;
111 1
            $template->setFilePath($viewFile);
112 1
            $template->setTemplateData(['name' => $controller]);
113
114 1
            $generator = new Generator\Generator($template);
115 1
            $generator->make();
116
        }
117
118 1
        return $this;
119
    }
120
121
    /**
122
     * @param InputInterface $input
123
     * @param OutputInterface $output
124
     * @return void
125
     * @throws \Bluzman\Generator\GeneratorException
126
     */
127 1
    public function verify(InputInterface $input, OutputInterface $output)
128
    {
129 1
        $modulePath = $this->getApplication()->getModulePath($input->getArgument('module'));
130
131
        $paths = [
132 1
            $modulePath,
133 1
            $modulePath . DS . 'controllers',
134 1
            $modulePath . DS . 'controllers' . DS . $input->getArgument('controller') . '.php',
135 1
            $modulePath . DS . 'views',
136 1
            $modulePath . DS . 'views' . DS . $input->getArgument('controller') . '.phtml',
137
138
        ];
139
140 1
        foreach ($paths as $path) {
141 1
            if (!$this->getFs()->exists($path)) {
142
                throw new Generator\GeneratorException("File or directory `$path` is not exists");
143
            }
144
        }
145 1
    }
146
}
147