Completed
Push — master ( 283542...d399c1 )
by Changwan
03:04
created

InstallCommand::execute()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 12
nc 3
nop 0
dl 0
loc 24
ccs 0
cts 15
cp 0
crap 12
rs 8.9713
c 0
b 0
f 0
1
<?php
2
namespace Wandu\Installation\Commands;
3
4
use Symfony\Component\Console\Input\InputInterface;
5
use Symfony\Component\Console\Output\OutputInterface;
6
use Symfony\Component\Console\Style\SymfonyStyle;
7
use Symfony\Component\Process\PhpExecutableFinder;
8
use Symfony\Component\Process\Process;
9
use Symfony\Component\Process\ProcessUtils;
10
use Wandu\Console\Command;
11
use Wandu\Installation\SkeletonBuilder;
12
13
class InstallCommand extends Command
14
{
15
    /** @var string */
16
    protected $description = "Install <comment>Wandu Framework</comment> to your project directory.";
17
18
    /** @var \Symfony\Component\Console\Style\SymfonyStyle */
19
    protected $io;
20
    
21
    /** @var array */
22
    protected $options = [
23
        'namespace?' => 'default wandu app namespace',
24
    ];
25
    
26
    /**
27
     * {@inheritdoc}
28
     */
29
    public function withIO(InputInterface $input, OutputInterface $output)
30
    {
31
        $this->io = new SymfonyStyle($input, $output);
32
        return parent::withIO($input, $output);
33
    }
34
35
    public function execute()
36
    {
37
        if (file_exists('.wandu.php')) {
38
            throw new \RuntimeException('already installed. if you want to re-install, remove the ".wandu.php" file!');
39
        }
40
41
        $this->output->writeln('Hello, <info>Welcome to Wandu Framework!</info>');
42
43
        $appBasePath = getcwd(); //static::filterPath($this->askAppBasePath('install path?', $basePath));
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
44
45
        $appNamespace = $this->input->hasOption('namespace') ?
46
            $this->input->getOption('namespace') :
47
            $this->askAppNamespace('app namespace?', 'Wandu\\App');
48
        
49
        $this->install($appBasePath, $appNamespace);
50
51
        // set composer
52
        $this->saveAutoloadToComposer($appNamespace);
53
54
        // run composer
55
        $this->runDumpAutoload();
56
57
        $this->output->writeln("<info>Install Complete!</info>");
58
    }
59
60
    protected function install($appBasePath, $appNamespace)
61
    {
62
        $installer = new SkeletonBuilder($appBasePath, __DIR__ . '/../skeleton');
63
        $replacers = [
64
            'WanduSkeleton' => $appNamespace,
65
        ];
66
        $installer->build($replacers);
67
68
        file_put_contents($appBasePath . '/.wandu.php', <<<PHP
69
<?php
70
71
define('WANDU_DB_HOST', 'localhost');
72
define('WANDU_DB_DBNAME', 'wandu');
73
define('WANDU_DB_USERNAME', 'root');
74
define('WANDU_DB_PASSWORD', 'root');
75
define('WANDU_DB_PREFIX', 'local_');
76
77
return new {$appNamespace}\ApplicationDefinition();
78
79
PHP
80
        );
81
    }
82
    
83
    protected function runDumpAutoload()
84
    {
85
        if (file_exists('composer.phar')) {
86
            $binary = ProcessUtils::escapeArgument((new PhpExecutableFinder)->find(false));
0 ignored issues
show
Security Bug introduced by
It seems like (new \Symfony\Component\...eFinder())->find(false) targeting Symfony\Component\Proces...xecutableFinder::find() can also be of type false; however, Symfony\Component\Proces...Utils::escapeArgument() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
87
            $composer = "{$binary} composer.phar";
88
        } else {
89
            $composer = 'composer';
90
        }
91
        (new Process("{$composer} dump-autoload", getcwd()))->run();
92
    }
93
94
    protected function saveAutoloadToComposer($appNamespace)
95
    {
96
        $this->output->write("save autoload setting to composer... ");
97
98
        $composerJson = [];
99
        if (file_exists('composer.json')) {
100
            $composerJson = json_decode(file_get_contents('composer.json'), true);
101
            if (json_last_error()) {
102
                $composerJson = [];
103
            }
104
        }
105
106
        if (!isset($composerJson['autoload'])) {
107
            $composerJson['autoload'] = [];
108
        }
109
        if (!isset($composerJson['autoload']['psr-4'])) {
110
            $composerJson['autoload']['psr-4'] = [];
111
        }
112
        $composerJson['autoload']['psr-4'][$appNamespace . '\\'] = 'src/';
113
        file_put_contents(
114
            'composer.json',
115
            json_encode($composerJson, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT) . "\n"
116
        );
117
        $this->output->writeln("<info>ok</info>");
118
    }
119
120
    protected function askAppNamespace($message, $default)
121
    {
122
        return $this->io->ask($message, $default, function ($namespace) {
123
            return rtrim($namespace, '\\');
124
        });
125
    }
126
127
    /**
128
     * @param string $message
129
     * @param string $default
130
     * @return string
131
     */
132
    protected function askAppBasePath($message, $default)
133
    {
134
        if (function_exists('posix_getuid')) {
135
            $info = posix_getpwuid(posix_getuid());
136
            $default = str_replace($info['dir'], '~', $default);
137
        }
138
        return $this->io->ask($message, $default);
139
    }
140
141
    /**
142
     * @param string $path
143
     * @return string
144
     */
145
    static protected function filterPath($path)
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
146
    {
147
        if ($path[0] === '~') {
148
            if (!function_exists('posix_getuid')) {
149
                throw new \InvalidArgumentException('cannot use tilde(~) character in your php environment.');
150
            }
151
            $info = posix_getpwuid(posix_getuid());
152
            $path = str_replace('~', $info['dir'], $path);
153
        }
154
155
        $basePath = getcwd();
156
        if ($path === $basePath) {
157
            $path = '.';
158
        } elseif (strpos($path, $basePath) === 0) {
159
            $path = str_replace("{$basePath}/", './', $path);
160
        } elseif ($path[0] === '/' || strpos($path, './') === 0) {
0 ignored issues
show
Unused Code introduced by
This elseif statement is empty, and could be removed.

This check looks for the bodies of elseif statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These elseif bodies can be removed. If you have an empty elseif but statements in the else branch, consider inverting the condition.

Loading history...
161
        } elseif (strpos($path, '..') === 0) {
162
            $path = realpath($basePath . '/' . $path);
163
        } else {
164
            $path = './' . $path;
165
        }
166
        return rtrim($path, '/');
167
    }
168
}
169