Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace DrupalCodeGenerator\Helper;
|
Chris@0
|
4
|
Chris@0
|
5 use DrupalCodeGenerator\Utils;
|
Chris@0
|
6 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
|
Chris@0
|
7 use Symfony\Component\Console\Helper\Helper;
|
Chris@0
|
8 use Symfony\Component\Console\Input\InputInterface;
|
Chris@0
|
9 use Symfony\Component\Console\Output\OutputInterface;
|
Chris@0
|
10 use Symfony\Component\Console\Question\ConfirmationQuestion;
|
Chris@0
|
11 use Symfony\Component\Filesystem\Filesystem;
|
Chris@0
|
12
|
Chris@0
|
13 /**
|
Chris@0
|
14 * Output dumper form generators.
|
Chris@0
|
15 */
|
Chris@0
|
16 class Dumper extends Helper {
|
Chris@0
|
17
|
Chris@0
|
18 /**
|
Chris@0
|
19 * The file system utility.
|
Chris@0
|
20 *
|
Chris@0
|
21 * @var \Symfony\Component\Filesystem\Filesystem
|
Chris@0
|
22 */
|
Chris@0
|
23 public $filesystem;
|
Chris@0
|
24
|
Chris@0
|
25 /**
|
Chris@0
|
26 * Input instance.
|
Chris@0
|
27 *
|
Chris@0
|
28 * @var \Symfony\Component\Console\Input\InputInterface
|
Chris@0
|
29 */
|
Chris@0
|
30 protected $input;
|
Chris@0
|
31
|
Chris@0
|
32 /**
|
Chris@0
|
33 * Output instance.
|
Chris@0
|
34 *
|
Chris@0
|
35 * @var \Symfony\Component\Console\Output\OutputInterface
|
Chris@0
|
36 */
|
Chris@0
|
37 protected $output;
|
Chris@0
|
38
|
Chris@0
|
39 /**
|
Chris@0
|
40 * Replace flag.
|
Chris@0
|
41 *
|
Chris@0
|
42 * @var bool
|
Chris@0
|
43 */
|
Chris@0
|
44 protected $replace;
|
Chris@0
|
45
|
Chris@0
|
46 /**
|
Chris@0
|
47 * Constructs a generator command.
|
Chris@0
|
48 *
|
Chris@0
|
49 * @param \Symfony\Component\Filesystem\Filesystem $filesystem
|
Chris@0
|
50 * The file system utility.
|
Chris@0
|
51 * @param bool $replace
|
Chris@0
|
52 * (optional) Indicates weather or not existing files can be replaced.
|
Chris@0
|
53 */
|
Chris@0
|
54 public function __construct(Filesystem $filesystem, $replace = NULL) {
|
Chris@0
|
55 $this->filesystem = $filesystem;
|
Chris@0
|
56 $this->replace = $replace;
|
Chris@0
|
57 }
|
Chris@0
|
58
|
Chris@0
|
59 /**
|
Chris@0
|
60 * {@inheritdoc}
|
Chris@0
|
61 */
|
Chris@0
|
62 public function getName() {
|
Chris@0
|
63 return 'dcg_dumper';
|
Chris@0
|
64 }
|
Chris@0
|
65
|
Chris@0
|
66 /**
|
Chris@0
|
67 * Dumps the generated code to file system.
|
Chris@0
|
68 *
|
Chris@0
|
69 * @param \Symfony\Component\Console\Input\InputInterface $input
|
Chris@0
|
70 * Input instance.
|
Chris@0
|
71 * @param \Symfony\Component\Console\Output\OutputInterface $output
|
Chris@0
|
72 * Output instance.
|
Chris@0
|
73 *
|
Chris@0
|
74 * @return array
|
Chris@0
|
75 * List of created or updated files.
|
Chris@0
|
76 */
|
Chris@0
|
77 public function dump(InputInterface $input, OutputInterface $output) {
|
Chris@0
|
78 $this->input = $input;
|
Chris@0
|
79 $this->output = $output;
|
Chris@0
|
80 $formatter_style = new OutputFormatterStyle('black', 'cyan', []);
|
Chris@0
|
81 $this->output->getFormatter()->setStyle('title', $formatter_style);
|
Chris@0
|
82
|
Chris@0
|
83 $interactive = $input->isInteractive();
|
Chris@0
|
84
|
Chris@0
|
85 // NULL means we should ask user for confirmation.
|
Chris@0
|
86 if ($this->replace !== NULL) {
|
Chris@0
|
87 $input->setInteractive(FALSE);
|
Chris@0
|
88 }
|
Chris@0
|
89
|
Chris@0
|
90 /** @var \DrupalCodeGenerator\Command\GeneratorInterface $command */
|
Chris@0
|
91 $command = $this->getHelperSet()->getCommand();
|
Chris@0
|
92
|
Chris@0
|
93 $dumped_files = $this->doDump($command->getAssets(), $command->getDirectory());
|
Chris@0
|
94
|
Chris@0
|
95 $input->setInteractive($interactive);
|
Chris@0
|
96 return $dumped_files;
|
Chris@0
|
97 }
|
Chris@0
|
98
|
Chris@0
|
99 /**
|
Chris@0
|
100 * Dumps assets.
|
Chris@0
|
101 *
|
Chris@0
|
102 * @param \DrupalCodeGenerator\Asset[] $assets
|
Chris@0
|
103 * Files to dump.
|
Chris@0
|
104 * @param string $directory
|
Chris@0
|
105 * Directory where to dump the assets.
|
Chris@0
|
106 *
|
Chris@0
|
107 * @return array
|
Chris@0
|
108 * List of created or updated assets.
|
Chris@0
|
109 */
|
Chris@0
|
110 protected function doDump(array $assets, $directory) {
|
Chris@0
|
111 $dumped_files = [];
|
Chris@0
|
112
|
Chris@0
|
113 foreach ($assets as $asset) {
|
Chris@0
|
114
|
Chris@0
|
115 $content = $asset->getContent();
|
Chris@0
|
116 $path = $asset->getPath();
|
Chris@0
|
117
|
Chris@0
|
118 $file_path = "$directory/$path";
|
Chris@0
|
119 if ($this->filesystem->exists($file_path) && !$asset->isDirectory()) {
|
Chris@0
|
120 $action = $asset->getAction();
|
Chris@0
|
121 if ($action == 'replace') {
|
Chris@0
|
122 $question_text = sprintf('<info>The file <comment>%s</comment> already exists. Would you like to replace it?</info> [<comment>Yes</comment>]:', $file_path);
|
Chris@0
|
123 if (!$this->confirm($question_text)) {
|
Chris@0
|
124 continue;
|
Chris@0
|
125 }
|
Chris@0
|
126 }
|
Chris@0
|
127 else {
|
Chris@0
|
128 $original_content = file_get_contents($file_path);
|
Chris@0
|
129 if ($action == 'append') {
|
Chris@0
|
130 $header_size = $asset->getHeaderSize();
|
Chris@0
|
131 // Do not remove header if original file is empty.
|
Chris@0
|
132 if ($original_content && $header_size > 0) {
|
Chris@0
|
133 $content = Utils::removeHeader($content, $header_size);
|
Chris@0
|
134 }
|
Chris@0
|
135 $content = $original_content . "\n" . $content;
|
Chris@0
|
136 }
|
Chris@0
|
137 elseif (is_callable($action)) {
|
Chris@0
|
138 $content = $action($original_content, $content);
|
Chris@0
|
139 }
|
Chris@0
|
140 else {
|
Chris@0
|
141 throw new \LogicException("Unsupported action: $action.");
|
Chris@0
|
142 }
|
Chris@0
|
143 }
|
Chris@0
|
144 }
|
Chris@0
|
145
|
Chris@0
|
146 // Default mode for all parent directories is 0777. It can be modified by
|
Chris@0
|
147 // changing umask.
|
Chris@0
|
148 $mode = $asset->getMode();
|
Chris@0
|
149
|
Chris@0
|
150 // Save data to file system.
|
Chris@0
|
151 if ($asset->isDirectory()) {
|
Chris@0
|
152 $this->filesystem->mkdir([$file_path], $mode);
|
Chris@0
|
153 }
|
Chris@0
|
154 else {
|
Chris@0
|
155 $this->filesystem->dumpFile($file_path, $content);
|
Chris@0
|
156 $this->filesystem->chmod($file_path, $mode);
|
Chris@0
|
157 }
|
Chris@0
|
158
|
Chris@0
|
159 $dumped_files[] = $asset->getPath();
|
Chris@0
|
160 }
|
Chris@0
|
161
|
Chris@0
|
162 return $dumped_files;
|
Chris@0
|
163 }
|
Chris@0
|
164
|
Chris@0
|
165 /**
|
Chris@0
|
166 * Asks a user for confirmation.
|
Chris@0
|
167 *
|
Chris@0
|
168 * @param string $question_text
|
Chris@0
|
169 * The question to ask to the user.
|
Chris@0
|
170 *
|
Chris@0
|
171 * @return bool
|
Chris@0
|
172 * User confirmation.
|
Chris@0
|
173 */
|
Chris@0
|
174 protected function confirm($question_text) {
|
Chris@0
|
175 $question_text = "\n $question_text\n ➤ ";
|
Chris@0
|
176 // If the input is not interactive print the question with default answer.
|
Chris@0
|
177 if ($this->replace !== NULL) {
|
Chris@0
|
178 $this->output->writeln($question_text . ($this->replace ? 'Yes' : 'No'));
|
Chris@0
|
179 }
|
Chris@0
|
180 $question = new ConfirmationQuestion($question_text, $this->replace !== FALSE);
|
Chris@0
|
181 /** @var \Symfony\Component\Console\Helper\QuestionHelper $question_helper */
|
Chris@0
|
182 $question_helper = $this->getHelperSet()->get('question');
|
Chris@0
|
183 return $question_helper->ask($this->input, $this->output, $question);
|
Chris@0
|
184 }
|
Chris@0
|
185
|
Chris@0
|
186 }
|