Completed
Push — master ( dfd004...b46837 )
by Jitendra
11s
created

InitCommand::prepareProjectPath()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 11
nc 6
nop 0
dl 0
loc 21
rs 8.7624
c 0
b 0
f 0
1
<?php
2
3
namespace Ahc\Phint\Console;
4
5
use Ahc\Phint\Generator\CollisionHandler;
6
use Ahc\Phint\Generator\TwigGenerator;
7
use Ahc\Phint\Util\Composer;
8
use Ahc\Phint\Util\Git;
9
use Ahc\Phint\Util\Inflector;
10
use Ahc\Phint\Util\Path;
11
use Symfony\Component\Console\Input\InputArgument;
12
use Symfony\Component\Console\Input\InputInterface;
13
use Symfony\Component\Console\Input\InputOption;
14
use Symfony\Component\Console\Output\OutputInterface;
15
16
class InitCommand extends BaseCommand
17
{
18
    /** @var Git */
19
    protected $git;
20
21
    /**
22
     * Configure the command options.
23
     *
24
     * @return void
25
     */
26
    protected function configure()
27
    {
28
        $this
29
            ->setName('init')
30
            ->setDescription('Create a bare new PHP project')
31
            ->addArgument('project', InputArgument::REQUIRED, 'The project name')
32
            ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force initialization even if the project exists')
33
            ->addOption('description', 'd', InputArgument::OPTIONAL, 'Project description')
34
            ->addOption('name', 'm', InputArgument::OPTIONAL, 'Vendor full name, defaults to git name')
35
            ->addOption('username', 'u', InputArgument::OPTIONAL, 'Vendor handle or username',
36
                getenv('GITHUB_USERNAME')
37
            )
38
            ->addOption('email', 'e', InputArgument::OPTIONAL, 'Vendor email, defaults to git email')
39
            ->addOption('namespace', 's', InputArgument::OPTIONAL, 'Root namespace')
40
            ->addOption('year', 'y', InputArgument::OPTIONAL, 'License Year', date('Y'))
41
            ->addOption('type', 't', InputArgument::OPTIONAL, 'Project type', 'library')
42
            ->addOption('using', 'z', InputArgument::OPTIONAL, 'Packagist name of reference project (eg: laravel/lumen)');
43
    }
44
45
    /**
46
     * Execute the command.
47
     *
48
     * @param InputInterface  $input
49
     * @param OutputInterface $output
50
     *
51
     * @return void
52
     */
53
    protected function execute(InputInterface $input, OutputInterface $output)
54
    {
55
        $this->input  = $input;
56
        $this->output = $output;
0 ignored issues
show
Documentation Bug introduced by
It seems like $output of type Symfony\Component\Console\Output\OutputInterface is incompatible with the declared type Ahc\Phint\Console\OutputInterface of property $output.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
57
58
        $output->writeln('<info>Preparing ...</info>');
59
60
        $projectPath = $this->prepareProjectPath();
61
        $this->git   = new Git($projectPath);
62
        $parameters  = $this->collectParameters();
63
        $composer    = new Composer;
64
65
        if (null !== $using = $this->input->getOption('using')) {
66
            $this->output->writeln('Using <comment>' . $using . '</comment> to create project');
67
68
            $composer->withOutput($this->output)->createProject($projectPath, $using);
69
        }
70
71
        $this->output->writeln('<comment>Generating files ...</comment>');
72
73
        $this->generate($projectPath, $parameters);
74
75
        $this->output->writeln('Setting up <info>git</info>');
76
77
        $this->git->init()->addRemote($parameters['username'], $parameters['project']);
78
79
        $this->output->writeln('Setting up <info>composer</info>');
80
81
        $composer->withWorkDir($projectPath)->install();
82
83
        $output->writeln('<comment>Done</comment>');
84
    }
85
86
    protected function prepareProjectPath()
87
    {
88
        $path = $this->input->getArgument('project');
89
90
        if (!(new Path)->isAbsolute($path)) {
91
            $path = \getcwd() . '/' . $path;
92
        }
93
94
        if (\file_exists($path)) {
95
            if (!$this->input->getOption('force')) {
96
                throw new \InvalidArgumentException('Something with the same name already exists!');
97
            }
98
99
            if (!$this->input->getOption('using')) {
100
                $this->output->writeln('<error>You have set force flag, existing files will be overwritten</error>');
101
            }
102
        } else {
103
            \mkdir($path, 0777, true);
104
        }
105
106
        return $path;
107
    }
108
109
    protected function collectParameters()
110
    {
111
        $inflector   = new Inflector;
112
        $project     = $this->input->getArgument('project');
113
        $Project     = $inflector->words($project);
114
        $year        = $this->input->getOption('year');
115
        $type        = $this->input->getOption('type');
116
        $vendorName  = $this->input->getOption('name') ?: $this->git->getConfig('user.name');
117
        $vendorEmail = $this->input->getOption('email') ?: $this->git->getConfig('user.email');
118
119
        $description = $this->input->getOption('description') ?: $this->prompt(
120
            'Project description [<comment>A brief intro about this project</comment>]: '
121
        );
122
123
        $username = $this->input->getOption('username') ?: $this->prompt(
124
            'Vendor Handle [<comment>Often your github username, set GITHUB_USERNAME env variable to automate</comment>]: '
125
        );
126
127
        $namespace = $inflector->stuldyCase($username) . '/' . $inflector->stuldyCase($project);
128
        $namespace = $this->input->getOption('namespace') ?: $this->prompt(
129
            'Root Namespace [<comment>Defaults to ' . $namespace . '</comment>]: ',
130
            $namespace
131
        );
132
133
        $namespace = \str_replace('/', '\\\\', $namespace);
134
        $keywords  = ['php', $project];
135
136
        return \compact(
137
            'year', 'project', 'vendorName', 'vendorEmail', 'description',
138
            'username', 'namespace', 'keywords', 'Project', 'type'
139
        );
140
    }
141
142
    protected function generate($projectPath, array $parameters)
143
    {
144
        $templatePath = __DIR__ . '/../../resources';
145
        $cachePath    = __DIR__ . '/../../.cache';
146
147
        $generator = new TwigGenerator($templatePath, $cachePath);
148
149
        $generator->generate($projectPath, $parameters, new CollisionHandler);
150
    }
151
}
152