Completed
Push — master ( e83215...d2e043 )
by Changwan
03:21
created

InstallCommand::askAppBasePath()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 5
nop 2
dl 0
loc 15
ccs 0
cts 15
cp 0
crap 20
rs 9.2
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\DI\ContainerInterface;
12
use Wandu\Installation\Replacers\OriginReplacer;
13
use Wandu\Installation\SkeletonBuilder;
14
15
class InstallCommand extends Command
16
{
17
    /** @var string */
18
    protected $description = "Install <comment>Wandu Framework</comment> to your project directory.";
19
20
    /** @var \Symfony\Component\Console\Style\SymfonyStyle */
21
    protected $io;
22
23
    /** @var string */
24
    protected $basePath;
25
26
    /** @var string */
27
    protected $appPath;
28
29
    public function __construct(ContainerInterface $container)
30
    {
31
        $this->basePath = $container['base_path'];
32
        $this->appPath = $container['app_path'];
33
    }
34
35
    /**
36
     * {@inheritdoc}
37
     */
38
    public function withIO(InputInterface $input, OutputInterface $output)
39
    {
40
        $this->io = new SymfonyStyle($input, $output);
41
        return parent::withIO($input, $output);
42
    }
43
44
    public function execute()
45
    {
46
        if (file_exists($this->appPath . '/.wandu.php')) {
47
            throw new \RuntimeException('already installed. if you want to re-install, remove the ".wandu.php" file!');
48
        }
49
50
        $this->output->writeln('Hello, <info>Welcome to Wandu Framework!</info>');
51
52
        $composerFile = $this->basePath . '/composer.json';
53
54
        $appBasePath = $this->askAppBasePath('install path?', $this->basePath);
55
        $appNamespace = $this->askAppNamespace('app namespace?', 'Wandu\\App');
56
57
//        $templateEngine = $this->io->choice(
0 ignored issues
show
Unused Code Comprehensibility introduced by
51% 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...
58
//            'template engine?',
59
//            ['php' => 'PHP', 'twig' => 'Twig(Sensio Labs)', 'latte' => 'Latte(Nette)', ],
60
//            'PHP'
61
//        );
62
//
63
//        $database = $this->io->choice(
64
//            'orm(database)?',
65
//            ['none' => 'None', 'eloquent' => 'Eloquent(Laravel)', ],
66
//            'None'
67
//        );
68
69
        $path = str_replace($this->basePath, '', $appBasePath);
70
        $path = ltrim($path ? $path . '/' : '', '/');
71
72
        $this->install($appBasePath, $appNamespace, $path);
73
74
        // set composer
75
        $this->saveAutoloadToComposer($appNamespace, $composerFile, $path);
76
77
        // run composer
78
        $this->runDumpAutoload($composerFile);
79
80
        $this->output->writeln("<info>Install Complete!</info>");
81
    }
82
83
    protected function install($appBasePath, $appNamespace, $path)
84
    {
85
        $installer = new SkeletonBuilder($appBasePath, __DIR__ . '/../skeleton');
86
87
        $replacers = [
88
            'YourOwnApp' => $appNamespace,
89
            '{path}' => $path,
90
            '%%origin%%' => new OriginReplacer(),
91
        ];
92
        $installer->build($replacers);
93
94
        file_put_contents($appBasePath . '/.wandu.php', <<<PHP
95
<?php
96
97
define('WANDU_DB_HOST', 'localhost');
98
define('WANDU_DB_DBNAME', 'wandu');
99
define('WANDU_DB_USERNAME', 'root');
100
define('WANDU_DB_PASSWORD', 'root');
101
define('WANDU_DB_PREFIX', 'local_');
102
103
return new {$appNamespace}\ApplicationDefinition();
104
105
PHP
106
        );
107
    }
108
    
109
    protected function runDumpAutoload($composerFile)
110
    {
111
        $basePath = dirname($composerFile);
112
        if (file_exists($basePath . '/composer.phar')) {
113
            $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...
114
            $composer = "{$binary} composer.phar";
115
        } else {
116
            $composer = 'composer';
117
        }
118
        (new Process("{$composer} dump-autoload", $basePath))->run();
119
    }
120
121
    protected function saveAutoloadToComposer($appNamespace, $composerFile, $path = '')
122
    {
123
        $this->output->write("save autoload setting to composer... ");
124
125
        $composerJson = [];
126
        if (file_exists($composerFile)) {
127
            $composerJson = json_decode(file_get_contents($composerFile), true);
128
            if (json_last_error()) {
129
                $composerJson = [];
130
            }
131
        }
132
133
        if (!isset($composerJson['autoload'])) {
134
            $composerJson['autoload'] = [];
135
        }
136
        if (!isset($composerJson['autoload']['psr-4'])) {
137
            $composerJson['autoload']['psr-4'] = [];
138
        }
139
        $composerJson['autoload']['psr-4'][$appNamespace . '\\'] = $path . 'src/';
140
        file_put_contents(
141
            $composerFile,
142
            json_encode($composerJson, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT) . "\n"
143
        );
144
        $this->output->writeln("<info>ok</info>");
145
    }
146
147
    protected function askAppNamespace($message, $default)
148
    {
149
        return $this->io->ask($message, $default, function ($namespace) {
150
            return rtrim($namespace, '\\');
151
        });
152
    }
153
154
    protected function askAppBasePath($message, $default)
155
    {
156
        $appBasePath = $this->io->ask($message, $default);
157
        if ($appBasePath[0] === '~') {
158
            if (!function_exists('posix_getuid')) {
159
                throw new \InvalidArgumentException('cannot use tilde(~) character in your php enviroment.');
160
            }
161
            $info = posix_getpwuid(posix_getuid());
162
            $appBasePath = str_replace('~', $info['dir'], $appBasePath);
163
        }
164
        if ($appBasePath[0] !== '/') {
165
            $appBasePath = $this->basePath . "/{$appBasePath}";
166
        }
167
        return rtrim($appBasePath, '/');
168
    }
169
}
170