CreateNotificationCommand::execute()   A
last analyzed

Complexity

Conditions 4
Paths 5

Size

Total Lines 37

Duplication

Lines 8
Ratio 21.62 %

Importance

Changes 0
Metric Value
dl 8
loc 37
rs 9.328
c 0
b 0
f 0
cc 4
nc 5
nop 2
1
<?php
2
3
namespace IrishDan\NotificationBundle\Command;
4
5
use IrishDan\NotificationBundle\Generator\NotificationGenerator;
6
use Sensio\Bundle\GeneratorBundle\Command\GeneratorCommand;
7
use Symfony\Component\Console\Input\InputInterface;
8
use Symfony\Component\Console\Input\InputOption;
9
use Symfony\Component\Console\Output\OutputInterface;
10
use Symfony\Component\Console\Question\ConfirmationQuestion;
11
use Symfony\Component\Console\Question\Question;
12
use Symfony\Component\Console\Style\SymfonyStyle;
13
14
15
class CreateNotificationCommand extends GeneratorCommand
16
{
17
    private $channels;
18
    private $channelTemplates = [];
19
20
    public function setEnabledChannels(array $channels)
21
    {
22
        $this->channels = $channels;
23
    }
24
25
    protected function configure()
26
    {
27
        $this
28
            ->setName('notification:create')
29
            ->setDescription('Create a new notification class')
30
            ->setDefinition(
31
                [
32
                    new InputOption('bundle', '', InputOption::VALUE_REQUIRED, 'The bundle for this notification'),
33
                    new InputOption(
34
                        'notification_name', '', InputOption::VALUE_REQUIRED, 'The name of the notification'
35
                    ),
36
                    new InputOption(
37
                        'channel_templates', '', InputOption::VALUE_REQUIRED, 'The name of the notification'
38
                    ),
39
                ]
40
            );
41
    }
42
43
    protected function interact(InputInterface $input, OutputInterface $output)
44
    {
45
        $questionHelper = $this->getQuestionHelper();
46
        $questionHelper->writeSection($output, 'Welcome to the Notification generator');
47
48
        // Get the Bundle to generate it in
49
        $output->writeln(
50
            [
51
                'This command helps you generate a Notification class',
52
                '',
53
                'First, give the name of the bundle to generate the notification in (eg <comment>AppBundle</comment>)',
54
            ]
55
        );
56
57
        $question = new Question(
58
            $questionHelper->getQuestion('The bundle name', $input->getOption('bundle')),
59
            $input->getOption('bundle')
60
        );
61
62
        // @TODO: Add existing bundle validation
63
        $question->setValidator(['Sensio\Bundle\GeneratorBundle\Command\Validators', 'validateBundleName']);
64
        $question->setNormalizer(
65
            function ($value) {
66
                return $value ? trim($value) : '';
67
            }
68
        );
69
        $question->setMaxAttempts(2);
70
71
        $bundle = $questionHelper->ask($input, $output, $question);
72
        $input->setOption('bundle', $bundle);
73
74
        // Get the Bundle to generate it in
75
        $output->writeln(
76
            [
77
                '',
78
                'Now, give the name of the new notification class (eg <comment>NewMember</comment>)',
79
            ]
80
        );
81
82
        // Get the new class name and validate it.
83
        $question = new Question(
84
            $questionHelper->getQuestion('The notification name', $input->getOption('notification_name')),
85
            $input->getOption('notification_name')
86
        );
87
        $question->setValidator(
88
            function ($answer) {
89
                // Should only contain letters.
90
                $valid = preg_match('/^[a-zA-Z]+$/', $answer);
91
                if (!$valid) {
92
                    throw new \RuntimeException(
93
                        'The class name should only contain letters'
94
                    );
95
                }
96
97
                return $answer;
98
            }
99
        );
100
        $question->setNormalizer(
101
            function ($value) {
102
                return $value ? trim($value) : '';
103
            }
104
        );
105
106
        $notificationName = $questionHelper->ask($input, $output, $question);
107
        $input->setOption('notification_name', $notificationName);
108
109
        // ask whether to generate templates for enabled channels.
110
        foreach ($this->channels as $channel) {
111
            $question = $this->createYesNoQuestion($questionHelper, $input, $channel);
112
113
            $generateTemplate = $questionHelper->ask($input, $output, $question);
114
            if ($generateTemplate == 'y') {
115
                $this->channelTemplates[] = $channel;
116
            }
117
        }
118
    }
119
120
    protected function execute(InputInterface $input, OutputInterface $output)
121
    {
122
        $questionHelper = $this->getQuestionHelper();
123
124 View Code Duplication
        if ($input->isInteractive()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
125
            $question = new ConfirmationQuestion(
126
                $questionHelper->getQuestion('Do you confirm generation', 'yes', '?'),
127
                true
128
            );
129
            if (!$questionHelper->ask($input, $output, $question)) {
130
                $output->writeln('<error>Command aborted</error>');
131
132
                return 1;
133
            }
134
        }
135
136
        $style = new SymfonyStyle($input, $output);
137
138
        $bundle = $input->getOption('bundle');
139
        $name = $input->getOption('notification_name');
140
141
        $style->text('Generating New notification class ' . $name . ' generated in ' . $bundle);
142
143
        try {
144
            $bundle = $this->getContainer()->get('kernel')->getBundle($bundle);
145
        } catch (\Exception $e) {
146
            $output->writeln(sprintf('<bg=red>Bundle "%s" does not exist.</>', $bundle));
147
        }
148
149
        $generator = $this->getGenerator($bundle);
150
        $generator->generate($bundle, $name);
151
152
        $output->writeln(
153
            sprintf('Generated the <info>%s</info> notification in <info>%s</info>', $name, $bundle->getName())
154
        );
155
        $questionHelper->writeGeneratorSummary($output, []);
156
    }
157
158
    protected function createYesNoQuestion($questionHelper, $input, $channel)
159
    {
160
        $question = new Question(
161
            $questionHelper->getQuestion(
162
                'Generate a message template for the "' . $channel . '" adapter <comment>[yes]</comment>',
163
                'channel_templates'
164
            ), 'yes'
165
        );
166
        $question->setNormalizer(
167
            function ($value) {
168
                return $value[0] == 'y' ? 'y' : 'n';
169
            }
170
        );
171
172
        $question->setValidator(
173
            function ($answer) {
174
                // Should only contain letters.
175
                $allowed = [
176
                    'y',
177
                    'n',
178
                ];
179
                $valid = in_array($answer, $allowed);
180
                if (!$valid) {
181
                    throw new \RuntimeException(
182
                        'Only allowed value are ' . implode(', ', $allowed)
183
                    );
184
                }
185
186
                return $answer;
187
            }
188
        );
189
190
        return $question;
191
    }
192
193
    protected function createGenerator()
194
    {
195
        return new NotificationGenerator(
196
            $this->getContainer()->get('filesystem'),
197
            $this->channelTemplates,
198
            $this->getContainer()->getParameter('kernel.root_dir')
199
        );
200
    }
201
}