Completed
Push — master ( 6d6774...64f3ed )
by Jeroen
11:23 queued 05:13
created

GeneratorBundle/Helper/InputAssistant.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Kunstmaan\GeneratorBundle\Helper;
4
5
use Sensio\Bundle\GeneratorBundle\Command\Helper\QuestionHelper;
6
use Sensio\Bundle\GeneratorBundle\Command\Validators;
7
use Symfony\Component\Console\Input\InputInterface;
8
use Symfony\Component\Console\Output\OutputInterface;
9
use Symfony\Component\Console\Question\Question;
10
use Symfony\Component\DependencyInjection\ContainerInterface;
11
use Symfony\Component\HttpKernel\Kernel;
12
13
/**
14
 * @deprecated the functions in this class should be moved to the KunstmaanGenerateCommand class
15
 */
16
class InputAssistant
17
{
18
    /** @var InputInterface */
19
    private $input;
20
21
    /** @var OutputInterface */
22
    private $output;
23
24
    /** @var QuestionHelper */
25
    private $questionHelper;
26
27
    /** @var Kernel */
28
    private $kernel;
29
30
    /** @var ContainerInterface */
31
    private $container;
32
33
    /**
34
     * @param InputInterface     $input
35
     * @param OutputInterface    $output
36
     * @param QuestionHelper     $questionHelper
37
     * @param Kernel             $kernel
38
     * @param ContainerInterface $container
39
     */
40
    public function __construct(InputInterface &$input, OutputInterface $output, QuestionHelper $questionHelper, Kernel $kernel, ContainerInterface $container)
41
    {
42
        $this->input = $input;
43
        $this->output = $output;
44
        $this->questionHelper = $questionHelper;
45
        $this->kernel = $kernel;
46
        $this->container = $container;
47
    }
48
49
    /**
50
     * Asks for the namespace and sets it on the InputInterface as the 'namespace' option, if this option is not set yet.
51
     *
52
     * @param array $text what you want printed before the namespace is asked
53
     *
54
     * @return string The namespace. But it's also been set on the InputInterface.
55
     */
56
    public function askForNamespace(array $text = null)
57
    {
58
        $namespace = $this->input->hasOption('namespace') ? $this->input->getOption('namespace') : null;
59
60
        // When the Namespace is filled in return it immediately if valid.
61
        try {
62
            if (!is_null($namespace) && !empty($namespace)) {
63
                Validators::validateBundleNamespace($namespace);
64
65
                return $namespace;
66
            }
67
        } catch (\Exception $error) {
68
            $this->writeError(array("Namespace '$namespace' is incorrect. Please provide a correct value.", $error->getMessage()));
69
            exit;
70
        }
71
72
        $ownBundles = $this->getOwnBundles();
73
        if (count($ownBundles) <= 0) {
74
            $this->writeError("Looks like you don't have created a bundle for your project, create one first.", true);
75
        }
76
77
        $namespace = '';
78
79
        // If we only have 1 or more bundles, we can prefill it.
80
        if (count($ownBundles) > 0) {
81
            $namespace = $ownBundles[1]['namespace'] . '/' . $ownBundles[1]['name'];
82
        }
83
84
        $namespaces = $this->getNamespaceAutoComplete($this->kernel);
85
86
        if (!is_null($text) && (count($text) > 0)) {
87
            $this->output->writeln($text);
0 ignored issues
show
$text is of type array, but the function expects a string|object<Symfony\Co...onsole\Output\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
88
        }
89
90
        $question = new Question($this->questionHelper->getQuestion('Bundle Namespace', $namespace), $namespace);
91
        $question->setValidator(array('Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateBundleNamespace'));
92
        $question->setAutocompleterValues($namespaces);
93
        $namespace = $this->questionHelper->ask($this->input, $this->output, $question);
94
95
        if ($this->input->hasOption('namespace')) {
96
            $this->input->setOption('namespace', $namespace);
97
        }
98
99
        return $namespace;
100
    }
101
102
    /**
103
     * Helper function to display errors in the console.
104
     *
105
     * @param $message
106
     * @param bool $exit
107
     */
108 View Code Duplication
    private function writeError($message, $exit = false)
109
    {
110
        $this->output->writeln($this->questionHelper->getHelperSet()->get('formatter')->formatBlock($message, 'error'));
111
        if ($exit) {
112
            exit;
113
        }
114
    }
115
116
    /**
117
     * Get an array with all the bundles the user has created.
118
     *
119
     * @return array
120
     */
121
    public function getOwnBundles()
122
    {
123
        $bundles = array();
124
        $counter = 1;
125
126
        $dir = dirname($this->container->getParameter('kernel.root_dir') . '/') . '/src/';
127
        $files = scandir($dir);
128
        foreach ($files as $file) {
129
            if (is_dir($dir . $file) && !in_array($file, array('.', '..'))) {
130
                $bundleFiles = scandir($dir . $file);
131
                foreach ($bundleFiles as $bundleFile) {
132
                    if (is_dir($dir . $file . '/' . $bundleFile) && !in_array($bundleFile, array('.', '..'))) {
133
                        $bundles[$counter++] = array(
134
                            'name' => $bundleFile,
135
                            'namespace' => $file,
136
                            'dir' => $dir . $file . '/' . $bundleFile,
137
                        );
138
                    }
139
                }
140
            }
141
        }
142
143
        return $bundles;
144
    }
145
146
    /**
147
     * Returns a list of namespaces as array with a forward slash to split the namespace & bundle.
148
     *
149
     * @param Kernel $kernel
150
     *
151
     * @return array
152
     */
153
    private function getNamespaceAutoComplete(Kernel $kernel)
154
    {
155
        $ret = array();
156
        foreach ($kernel->getBundles() as $k => $v) {
157
            $ret[] = $this->fixNamespace($v->getNamespace());
158
        }
159
160
        return $ret;
161
    }
162
163
    /**
164
     * Replaces '\' with '/'.
165
     *
166
     * @param $namespace
167
     *
168
     * @return mixed
169
     */
170
    private function fixNamespace($namespace)
171
    {
172
        return strtr($namespace, array('\\Bundle\\' => '/', '\\' => '/'));
173
    }
174
175
    /**
176
     * Asks for the prefix and sets it on the InputInterface as the 'prefix' option, if this option is not set yet.
177
     * Will set the default to a snake_cased namespace when the namespace has been set on the InputInterface.
178
     *
179
     * @param array  $text      What you want printed before the prefix is asked. If null is provided it'll write a default text.
180
     * @param string $namespace An optional namespace. If this is set it'll create the default based on this prefix.
181
     *                          If it's not provided it'll check if the InputInterface already has the namespace option.
182
     *
183
     * @return string The prefix. But it's also been set on the InputInterface.
184
     */
185
    public function askForPrefix(array $text = null, $namespace = null)
186
    {
187
        $prefix = $this->input->hasOption('prefix') ? $this->input->getOption('prefix') : null;
188
189
        if (is_null($text)) {
190
            $text = array(
191
                '',
192
                'You can add a prefix to the table names of the generated entities for example: <comment>projectname_bundlename_</comment>',
193
                'Enter an underscore \'_\' if you don\'t want a prefix.',
194
                '',
195
            );
196
        }
197
198
        while (is_null($prefix)) {
199
            if (count($text) > 0) {
200
                $this->output->writeln($text);
0 ignored issues
show
$text is of type null|array, but the function expects a string|object<Symfony\Co...onsole\Output\iterable>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
201
            }
202
203
            if (is_null($namespace) || empty($namespace)) {
204
                $namespace = $this->input->hasOption('namespace') ? $this->input->getOption('namespace') : null;
205
            } else {
206
                $namespace = $this->fixNamespace($namespace);
207
            }
208
            $defaultPrefix = GeneratorUtils::cleanPrefix($this->convertNamespaceToSnakeCase($namespace));
209
            $question = new Question($this->questionHelper->getQuestion('Tablename prefix', $defaultPrefix), $defaultPrefix);
210
            $prefix = $this->questionHelper->ask($this->input, $this->output, $question);
211
            $prefix = GeneratorUtils::cleanPrefix($prefix);
212
            if ($this->input->hasOption('prefix')) {
213
                $this->input->setOption('prefix', $prefix);
214
            }
215
216
            if ($prefix == '') {
217
                break;
218
            }
219
220 View Code Duplication
            if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $prefix)) {
221
                $this->output->writeln(sprintf('<bg=red> "%s" contains invalid characters</>', $prefix));
222
                $prefix = $text = null;
223
224
                continue;
225
            }
226
        }
227
228
        return $prefix;
229
    }
230
231
    /**
232
     * Converts something like Namespace\BundleNameBundle to namspace_bundlenamebundle.
233
     *
234
     * @param string $namespace
235
     *
236
     * @return string
237
     */
238 View Code Duplication
    private function convertNamespaceToSnakeCase($namespace)
239
    {
240
        if (is_null($namespace)) {
241
            return null;
242
        }
243
244
        return str_replace('/', '_', strtolower($this->fixNamespace($namespace)));
245
    }
246
}
247