Completed
Push — master ( 79d230...9a06a5 )
by Pierre
10s
created

CreateCommand   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 158
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 25.76%

Importance

Changes 6
Bugs 2 Features 1
Metric Value
wmc 16
c 6
b 2
f 1
lcom 1
cbo 4
dl 0
loc 158
ccs 17
cts 66
cp 0.2576
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A askForPackageName() 0 20 3
A askForDescription() 0 9 2
A isValidEmail() 0 13 3
A askForAuthor() 0 20 3
A parseAuthorString() 0 15 3
A __construct() 0 5 1
A __invoke() 0 23 1
1
<?php
2
3
namespace Ptondereau\PackMe\Commands;
4
5
use Ptondereau\PackMe\Crafters\CrafterInterface;
6
use Ptondereau\PackMe\Package;
7
use Symfony\Component\Console\Helper\HelperSet;
8
use Symfony\Component\Console\Input\InputInterface;
9
use Symfony\Component\Console\Output\OutputInterface;
10
11
/**
12
 * Class CreateCommand.
13
 */
14
class CreateCommand extends AbstractBaseCommand
15
{
16
    /**
17
     * Crafter.
18
     *
19
     * @var CrafterInterface
20
     */
21
    protected $crafter;
22
23
    /**
24
     * CreateCommand constructor.
25
     *
26
     * @param CrafterInterface $crafter
27
     * @param HelperSet        $helperSet
28
     */
29 9
    public function __construct(CrafterInterface $crafter, HelperSet $helperSet)
30
    {
31 9
        parent::__construct($helperSet);
32 9
        $this->crafter = $crafter;
33 9
    }
34
35
    public function __invoke($dir, InputInterface $input, OutputInterface $output)
36
    {
37
        $this->input = $input;
38
        $this->output = $output;
39
40
        $output->writeln('<info>I need to know a little more about your future awesome laravel package...</info>');
41
        $output->writeln('');
42
43
        $package = new Package(
44
            $this->askForPackageName(),
45
            $this->askForAuthor(),
46
            $dir
47
        );
48
        $package->setDescription($this->askForDescription());
49
50
        $output->writeln('');
51
        $output->writeln('<info>Crafting your laravel package...</info>');
52
53
        $this->crafter->craft($package);
54
55
        $output->writeln('');
56
        $output->writeln('<info>Successfully crafted!</info>');
57
    }
58
59
    /**
60
     * @param string $package
61
     *
62
     * @return string
63
     */
64
    protected function askForPackageName($package = 'vendor/package')
65
    {
66
        return $this->askAndValidate(
67
            'Package name (<vendor>/<name>) [<comment>'.$package.'</comment>]: ',
68
            function ($value) use ($package) {
69
                if (null === $value) {
70
                    return $package;
71
                }
72
                if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $value)) {
73
                    throw new \InvalidArgumentException(
74
                        'The package name '.$value.' is invalid, it should be lowercase and have a vendor name, a forward slash, and a package name, matching: [a-z0-9_.-]+/[a-z0-9_.-]+'
75
                    );
76
                }
77
78
                return $value;
79
            },
80
            null,
81
            $package
82
        );
83
    }
84
85
    /**
86
     * @param string $author
87
     *
88
     * @return string
89
     */
90
    protected function askForAuthor($author = 'Author Name <[email protected]>')
91
    {
92
        $self = $this;
93
94
        return $this->askAndValidate(
95
            'Author [<comment>'.$author.'</comment>]: ',
96
            function ($value) use ($self, $author) {
97
                if (null === $value) {
98
                    return $author;
99
                }
100
101
                $value = $value ?: $author;
102
                $parsed = $self->parseAuthorString($value);
103
104
                return sprintf('%s <%s>', $parsed['name'], $parsed['email']);
105
            },
106
            null,
107
            $author
108
        );
109
    }
110
111
    /**
112
     * @param bool|string $description
113
     *
114
     * @return string
115
     */
116
    protected function askForDescription($description = false)
117
    {
118
        $description = $description ?: false;
119
120
        return $this->ask(
121
            'Description [<comment>'.$description.'</comment>]: ',
122
            $description
123
        );
124
    }
125
126
    /**
127
     * Parse the author string.
128
     *
129
     * @private
130
     *
131
     * @param string $author
132
     *
133
     * @return array
134
     */
135 9
    private function parseAuthorString($author)
136
    {
137 9
        if (preg_match('/^(?P<name>[- \.,\p{L}\p{N}\'’]+) <(?P<email>.+?)>$/u', $author, $match)) {
138 6
            if ($this->isValidEmail($match['email'])) {
139
                return [
140 3
                    'name'  => trim($match['name']),
141 3
                    'email' => $match['email'],
142 3
                ];
143
            }
144 3
        }
145 6
        throw new \InvalidArgumentException(
146
            'Invalid author string.  Must be in the format: '.
147
            'John Smith <[email protected]>'
148 6
        );
149
    }
150
151
    /**
152
     * Check if a given email is a good email.
153
     *
154
     * @param $email
155
     *
156
     * @return bool
157
     */
158 6
    private function isValidEmail($email)
159
    {
160
        // assume it's valid if we can't validate it
161 6
        if (!function_exists('filter_var')) {
162
            return true;
163
        }
164
        // php <5.3.3 has a very broken email validator, so bypass checks
165 6
        if (PHP_VERSION_ID < 50303) {
166
            return true;
167
        }
168
169 6
        return false !== filter_var($email, FILTER_VALIDATE_EMAIL);
170
    }
171
}
172