ViewCreate::configure()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 0
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
1
<?php
2
// +---------------------------------------------------------------------------+
3
// | This file is part of the Agavi package.                                   |
4
// | Copyright (c) 2005-2016 the Agavi Project.                                |
5
// |                                                                           |
6
// | For the full copyright and license information, please view the LICENSE   |
7
// | file that was distributed with this source code. You can also view the    |
8
// | LICENSE file online at http://www.agavi.org/LICENSE.txt                   |
9
// |   vi: set noexpandtab:                                                    |
10
// |   Local Variables:                                                        |
11
// |   indent-tabs-mode: t                                                     |
12
// |   End:                                                                    |
13
// +---------------------------------------------------------------------------+
14
/**
15
 * Create view and template
16
 *
17
 * @author     Markus Lervik <[email protected]>
18
 * @copyright  Authors
19
 * @copyright  The Agavi Project
20
 *
21
 * @since      2.0.0
22
 **/
23
24
namespace Agavi\Build\Console\Command;
25
26
use Symfony\Component\Console\Exception\InvalidArgumentException;
27
use Symfony\Component\Console\Input\InputArgument;
28
use Symfony\Component\Console\Input\InputInterface;
29
use Symfony\Component\Console\Input\InputOption;
30
use Symfony\Component\Console\Output\Output;
31
use Symfony\Component\Console\Output\OutputInterface;
32
use Symfony\Component\Console\Question\Question;
33
use Symfony\Component\Yaml\Yaml;
34
35
class ViewCreate extends AgaviCommand
36
{
37
    protected function configure()
38
    {
39
        $this->setName('agavi:view')
40
            ->setDescription('Create view')
41
            ->addArgument('view', InputArgument::OPTIONAL, 'The name of the view. If it\'s not provided, it will be asked for.')
42
            ->addOption('module', 'm', InputOption::VALUE_REQUIRED, 'The module that the view belongs to. If it\'s not provided, it will be asked for.')
43
            ->addOption('controller', 'c', InputOption::VALUE_REQUIRED, 'The controller that the view belongs to. If it\'s not provided, it will be asked for.')
44
            ->addOption('settings', 's', InputOption::VALUE_REQUIRED, '.settings.yml to read configuration from')
45
            ->addOption('output-types', 'ot', InputOption::VALUE_REQUIRED, 'Quoted space separated list of output types the controller should have. If it\'s not provided, it will be asked for.');
46
    }
47
48
    public function execute(InputInterface $input, OutputInterface $output)
49
    {
50
51 View Code Duplication
        if ($input->hasOption('settings') && $input->getOption('settings') != null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
52
            $settingsFile = $input->getOption('settings');
53
        } else {
54
            $settingsFile = '.' . DIRECTORY_SEPARATOR . '.settings.yml';
55
        }
56
57
        if (!file_exists($settingsFile)) {
58
            throw new InvalidArgumentException(sprintf('Cannot find settings file "%s"', $settingsFile));
59
        }
60
61
        $helper = $this->getHelper('question');
62
63
        $settings = Yaml::parse(file_get_contents($settingsFile));
64
65
        if (!is_array($settings)) {
66
            throw new InvalidArgumentException(sprintf('Error parsing settings file "%s". Return value unexpected. Expected array, got %s', $settingsFile, gettype($settings)));
67
        }
68
69
        if (!isset($settings['project']['prefix'])) {
70
            throw new InvalidArgumentException(sprintf('No project prefix found in settings file "%s"', $settingsFile));
71
        }
72
        $projectLocation = (is_array($settings) && isset($settings['project']['location']) ? $settings['project']['location'] : '.');
73
74
        $output->writeln(sprintf("Project location set to \"%s\"", $projectLocation), Output::VERBOSITY_VERY_VERBOSE);
75
76
        if ($input->hasOption('module') && $input->getOption('module') != null) {
77
            $module = $input->getOption('module');
78
        } else {
79
            $question = new Question("Module name: ");
80
            $module = $helper->ask($input, $output, $question);
81
        }
82
83
        $module = ucfirst(TransformIdentifier::transform($module));
84
85
        $output->writeln(sprintf("Module name transformed to to \"%s\"", $module), Output::VERBOSITY_VERY_VERBOSE);
86
87
88 View Code Duplication
        if (!file_exists($projectLocation . '/app/modules/' . $module . '/config/module.xml')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
89
            throw new InvalidArgumentException(sprintf('Module "%s" does not seem to exist in "%s"', $module, implode(DIRECTORY_SEPARATOR, [$projectLocation, 'app', 'modules', $module])));
90
        }
91
92
        if ($input->hasOption('controller') && $input->getOption('controller') != null) {
93
            $controllerName = $input->getOption('controller');
94
        } else {
95
            $question = new Question('Controller name: ');
96
            $controllerName = $helper->ask($input, $output, $question);
97
        }
98
99
        if (strlen($controllerName) == 0) {
100
            throw new InvalidArgumentException("Controller name cannot be empty.");
101
        }
102
103 View Code Duplication
        if (!file_exists($projectLocation . '/app/modules/' . $module . '/controllers/' . str_replace('.', '/', $controllerName) . 'Controller.class.php')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
104
            throw new InvalidArgumentException(sprintf('Controller "%s" does not seem to exist in "%s"', $controllerName, $projectLocation .
105
                implode(DIRECTORY_SEPARATOR, ['app', 'modules', $module, 'controllers', explode('.', $controllerName)]) . 'Controller.class.php'));
106
        }
107
108
        $controllerName = TransformIdentifier::transform($controllerName);
109
        $output->writeln(sprintf("Controller name transformed to  \"%s\"", $controllerName), Output::VERBOSITY_VERY_VERBOSE);
110
111
        if ($input->hasArgument('view') && $input->getArgument('view') != null) {
112
            $viewName = $input->getArgument('view');
113
        } else {
114
            $question = new Question('View name: ');
115
            $viewName = $helper->ask($input, $output, $question);
116
        }
117
118
        if (strlen($viewName) == 0) {
119
            throw new InvalidArgumentException("Controller name cannot be empty.");
120
        }
121
122
        if (file_exists($projectLocation . '/app/modules/' . $module . '/views/' . str_replace('.', '/', $controllerName) . $viewName . 'View.class.php')) {
123
            throw new InvalidArgumentException(sprintf('View "%s" seems to already exist in "%s"', $controllerName . $viewName, $projectLocation .
124
                implode(DIRECTORY_SEPARATOR, ['app', 'modules', $module, 'views', explode('.', $controllerName)]) . $viewName . 'View.class.php'));
125
        }
126
127
        $viewName = TransformIdentifier::transform($viewName);
128
        $output->writeln(sprintf("View name transformed to  \"%s\"", $viewName), Output::VERBOSITY_VERY_VERBOSE);
129
130
        $fc = new FileCopyHelper();
131
132
        if ($input->hasOption('output-types') && $input->getOption('output-types') != null) {
133
            // Remove quotes and turn input into an array
134
            $output_types = explode(' ', str_replace('"', '', $input->getOption('output-types')));
135
        } else {
136
            // Ask for the input types
137
            $question = new Question(sprintf("Space-separated list of output-types handled by the view [%s] (empty for none): ", $controllerName . ucfirst($viewName)));
138
            $output_types = $helper->ask($input, $output, $question);
139
            $output_types = explode(' ', $output_types);
140
        }
141
142
        $output->writeln('Copying view', Output::VERBOSITY_VERY_VERBOSE);
143
144
        $viewFile = $projectLocation . '/app/modules/' . $module . '/views/' . str_replace('.', '/', $controllerName) . ucfirst($viewName) . 'View.class.php';
145
146
        $output->writeln(sprintf("[%s -> %s]",
147
            $this->getSourceDir() . '/build/templates/app/modules/views/View.class.php.tmpl',
148
            $viewFile
149
        ), Output::VERBOSITY_DEBUG);
150
151
        $srcview = $this->getSourceDir() . '/build/templates/app/modules/views/View.class.php.tmpl';
152
153
        $fc->copy($srcview, $viewFile,
154 View Code Duplication
            function ($data, $params) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
155
                return str_replace([
156
                    '%%PROJECT_PREFIX%%',
157
                    '%%MODULE_NAME%%',
158
                    '%%VIEW_CLASS%%',
159
                    '%%METHOD_DECLARATIONS%%',
160
                    '%%PROJECT_NAMESPACE%%',
161
                    '%%FQNS%%'
162
                ], [
163
                    $params['projectPrefix'],
164
                    $params['moduleName'],
165
                    $params['viewClass'],
166
                    $params['methodDeclarations'],
167
                    $params['NS'],
168
                    $params['FQNS']
169
                ], $data);
170
            }, [
171
                'projectPrefix' => $settings['project']['prefix'],
172
                'moduleName' => $module,
173
                'viewClass' => $module . '_' . $controllerName . ucfirst($viewName) . 'View',
174
                'methodDeclarations' => $this->generateHandleOutputTypeMethods($output_types, $controllerName),
175
                'FQNS' => $settings['project']['namespace'],
176
                'NS' => substr($settings['project']['namespace'], 1, strlen($settings['project']['namespace']))
177
            ]
178
        );
179
180
        $templateFile = $projectLocation . '/app/modules/' . $module . '/templates/' . str_replace('.', '/', $controllerName) . ucfirst($viewName) . '.php';
181
182
        $output->writeln(sprintf('Creating empty template file "%s"', $templateFile), Output::VERBOSITY_DEBUG);
183
        @touch($templateFile, 0755);
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...
184
    }
185
186
    /**
187
     * Generate the execute<OutputType> -methods
188
     *
189
     * @param array $output_types an array of OutputTypes
190
     * @param string $controllerName the controller name
191
     * @return string the generated execute-methods
192
     */
193 View Code Duplication
    private function generateHandleOutputTypeMethods(array $output_types, string $controllerName)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
194
    {
195
        $tmpl = file_get_contents($this->getSourceDir() . '/build/templates/code/views/HandleOutputType.tmpl');
196
197
        $code = '';
198
        foreach ($output_types as $output_type) {
199
            $code .= str_replace(['%%OUTPUT_TYPE_NAME%%', '%%CONTROLLER_NAME%%'], [ucfirst($output_type), $controllerName], $tmpl);
200
        }
201
        return $code;
202
    }
203
}
204