3 namespace DrupalCodeGenerator\Command;
5 use DrupalCodeGenerator\ApplicationFactory;
6 use DrupalCodeGenerator\Asset;
7 use DrupalCodeGenerator\Utils;
8 use Symfony\Component\Console\Command\Command;
9 use Symfony\Component\Console\Input\InputInterface;
10 use Symfony\Component\Console\Input\InputOption;
11 use Symfony\Component\Console\Output\OutputInterface;
14 * Base class for all generators.
16 abstract class BaseGenerator extends Command implements GeneratorInterface {
26 * The command description.
30 protected $description;
47 * A path where templates are stored.
51 protected $templatePath;
54 * The working directory.
65 protected $destination = 'modules/%';
70 * The key of the each item in the array is the path to the file and
71 * the value is the generated content of it.
75 * @deprecated Use self::$assets.
77 protected $files = [];
82 * @var \DrupalCodeGenerator\Asset[]
84 protected $assets = [];
87 * Twig template variables.
96 protected function configure() {
98 ->setName($this->name)
99 ->setDescription($this->description)
103 InputOption::VALUE_OPTIONAL,
109 InputOption::VALUE_OPTIONAL,
110 'Default JSON formatted answers'
114 $this->setAliases([$this->alias]);
117 if (!$this->templatePath) {
118 $this->templatePath = ApplicationFactory::getRoot() . '/templates';
125 protected function initialize(InputInterface $input, OutputInterface $output) {
126 $this->getHelperSet()->setCommand($this);
127 $this->getHelper('dcg_renderer')->addPath($this->templatePath);
129 $directory = $input->getOption('directory') ?: getcwd();
130 // No need to look up for extension root when generating an extension.
131 $extension_destinations = ['modules', 'profiles', 'themes'];
132 $is_extension = in_array($this->destination, $extension_destinations);
133 $this->directory = $is_extension
134 ? $directory : (Utils::getExtensionRoot($directory) ?: $directory);
136 // Display welcome message.
138 "\n Welcome to %s generator!",
141 $output->writeln($header);
142 $header_length = strlen(trim(strip_tags($header)));
143 $output->writeln('<fg=cyan;options=bold>–' . str_repeat('–', $header_length) . '–</>');
149 protected function execute(InputInterface $input, OutputInterface $output) {
151 // Render all assets.
152 $renderer = $this->getHelper('dcg_renderer');
153 foreach ($this->getAssets() as $asset) {
154 // Supply the asset with all collected variables if it has no local ones.
155 if (!$asset->getVars()) {
156 $asset->vars($this->vars);
158 $asset->render($renderer);
161 $dumped_files = $this->getHelper('dcg_dumper')->dump($input, $output);
162 $this->getHelper('dcg_output_handler')->printSummary($output, $dumped_files);
169 public function getLabel() {
174 * Returns list of rendered files.
177 * An associative array where each key is path to a file and value is
182 public function getFiles() {
189 public function getAssets() {
191 // Convert files into assets for legacy commands.
193 foreach ($this->getFiles() as $path => $file) {
194 $asset = new Asset();
196 if (!is_array($file)) {
197 $file = ['content' => $file];
199 if (isset($file['content'])) {
200 $asset->content($file['content']);
203 $asset->type('directory');
205 if (isset($file['action'])) {
206 $asset->action($file['action']);
208 if (isset($file['header_size'])) {
209 $asset->headerSize($file['header_size']);
211 if (isset($file['mode'])) {
212 $asset->mode($file['mode']);
216 return array_merge($assets, $this->assets);
219 return $this->assets;
225 public function setDirectory($directory) {
226 $this->directory = $directory;
232 public function getDirectory() {
233 return $this->directory;
239 public function setDestination($destination) {
240 $this->destination = $destination;
246 public function getDestination() {
247 return $this->destination;
251 * Renders a template.
253 * @param string $template
256 * Template variables.
259 * A string representing the rendered output.
261 protected function render($template, array $vars) {
262 return $this->getHelper('dcg_renderer')->render($template, $vars);
266 * Asks the user for template variables.
268 * @param \Symfony\Component\Console\Input\InputInterface $input
270 * @param \Symfony\Component\Console\Output\OutputInterface $output
272 * @param array $questions
273 * List of questions that the user should answer.
275 * Array of predefined template variables.
278 * Template variables.
280 * @see \DrupalCodeGenerator\InputHandler
282 protected function &collectVars(InputInterface $input, OutputInterface $output, array $questions, array $vars = []) {
283 $this->vars += $this->getHelper('dcg_input_handler')->collectVars($input, $output, $questions, $vars);
290 * @param string $type
293 * @return \DrupalCodeGenerator\Asset
296 protected function addAsset($type) {
297 $asset = (new Asset())->type($type);
298 $this->assets[] = $asset;
303 * Creates file asset.
305 * @return \DrupalCodeGenerator\Asset
308 protected function addFile() {
309 return $this->addAsset('file');
313 * Creates directory asset.
315 * @return \DrupalCodeGenerator\Asset
318 protected function addDirectory() {
319 return $this->addAsset('directory');
323 * Creates service file asset.
325 * @return \DrupalCodeGenerator\Asset
328 protected function addServicesFile() {
329 return $this->addFile()
330 ->path('{machine_name}.services.yml')
336 * Creates file asset.
338 * @param string $path
340 * @param string $template
341 * Twig template to render.
345 * @deprecated Use self::addFile() or self::addDirectory().
347 protected function setFile($path = NULL, $template = NULL, array $vars = []) {
350 ->template($template)
355 * Creates service file asset.
357 * @param string $path
359 * @param string $template
360 * Twig template to render.
364 * @deprecated Use self::addServiceFile().
366 protected function setServicesFile($path, $template, array $vars) {
367 $this->addServicesFile()
369 ->template($template)