Skip to content

Commit

Permalink
[composerize] Add command. (#3643)
Browse files Browse the repository at this point in the history
* [composerize] Add command.

* [composerize] Remove dependent packages.

* [composerize] Add show-packages and include-version options.

* [composerize] Add .gitinore file instructions.

* [composerize] Exctract code to processModules method.

* [composerize] Group packages by extension.

* [composerize] Add processThemes method.

* [composerize] Process only no-core themes.
  • Loading branch information
jmolivas authored Jan 7, 2018
1 parent 115b81e commit 268569a
Show file tree
Hide file tree
Showing 2 changed files with 229 additions and 0 deletions.
6 changes: 6 additions & 0 deletions services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,9 @@ services:
console.annotation_validator:
class: Drupal\Console\Utils\AnnotationValidator
arguments: ['@console.annotation_command_reader', '@console.extension_manager']
# Commands
console.generate_composer:
class: Drupal\Console\Command\ComposerizeCommand
tags:
- { name: drupal.command }

223 changes: 223 additions & 0 deletions src/Command/ComposerizeCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
<?php

namespace Drupal\Console\Command;

use Drupal\Console\Core\Style\DrupalStyle;
use Drupal\Console\Extension\Manager;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Drupal\Console\Core\Command\ContainerAwareCommand;

class ComposerizeCommand extends ContainerAwareCommand
{
protected $packages = [];

protected $dependencies = [];

/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('composerize')
->setDescription(
$this->trans('commands.composerize.description')
)
->addOption(
'hide-packages',
null,
InputOption::VALUE_NONE,
$this->trans('commands.composerize.options.hide-packages')
)
->addOption(
'include-version',
null,
InputOption::VALUE_NONE,
$this->trans('commands.composerize.options.include-version')
)
->setHelp($this->trans('commands.composerize.help'));
}

/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
/**
* @var DrupalStyle $io
*/
$io = new DrupalStyle($input, $output);
$includeVersion = $input->getOption('include-version');
$hidePackages = $input->getOption('hide-packages')?:false;

/**
* @var \Drupal\Console\Extension\Manager $extensionManager
*/
$extensionManager = $this->get('console.extension_manager');
$this->processModules($extensionManager);
$this->processThemes($extensionManager);

$types = [
'module',
'theme'
];

$composerCommand = 'composer require ';
foreach ($types as $type) {
$packages = $this->packages[$type];
if (!$packages) {
continue;
}
if (!$hidePackages) {
$io->comment(ucfirst($type).'(s) detected.');
$tableHeader = ['Name', 'Version', 'Dependencies'];
$io->table($tableHeader, $packages);
}
foreach ($packages as $package) {
$module = str_replace('drupal/', '', $package['name']);
if (in_array($module, $this->dependencies[$type])) {
continue;
}
$composerCommand .= $package['name'];
if ($includeVersion) {
$composerCommand .= ':' . $package['version'];
}
$composerCommand .= ' ';
}
}
$io->comment('From your project root:');
$io->simple($this->get('console.root'));
$io->newLine();
$io->comment('Execute this command:');
$io->simple($composerCommand);
$io->newLine();
$io->comment('To ignore third party libraries, modules and themes add to your .gitignore file:');
$io->writeln(
[
' /vendor/',
' /modules/contrib',
' /themes/contrib'
]
);
}

private function processModules(Manager $extensionManager)
{
$type = 'module';
$modules = $extensionManager->discoverModules()
->showInstalled()
->showNoCore()
->getList();

/**
* @var \Drupal\Core\Extension\Extension[] $module
*/
foreach ($modules as $module) {
if (!$this->isValidModule($module)) {
continue;
}
$moduleDependencies = $this->extractDependencies(
$module,
array_keys($modules)
);
$this->packages[$type][] = [
'name' => sprintf('drupal/%s', $module->getName()),
'version' => $this->calculateVersion($module->info['version']),
'dependencies' => implode(', ', array_values($moduleDependencies))
];
$this->dependencies[$type] = array_merge(
$this->dependencies[$type],
array_keys($moduleDependencies)
);
}
}

private function processThemes(Manager $extensionManager)
{
$type = 'theme';
$themes = $extensionManager->discoverThemes()
->showInstalled()
->showNoCore()
->getList();
/**
* @var \Drupal\Core\Extension\Extension[] $module
*/
foreach ($themes as $theme) {
if (!$this->isValidTheme($theme)) {
continue;
}
$this->packages[$type][] = [
'name' => sprintf('drupal/%s', $theme->getName()),
'version' => $this->calculateVersion($theme->info['version']),
'dependencies' => ''
];
}
}

private function isValidModule($module)
{
if (strpos($module->getPath(), 'modules/custom') === 0) {
return false;
}

if (!array_key_exists('project', $module->info)) {
return true;
}

if (!array_key_exists('project', $module->info)) {
return true;
}

return $module->info['project'] === $module->getName();
}

private function isValidTheme($module)
{
if (strpos($module->getPath(), 'themes/custom') === 0) {
return false;
}

return true;
}

private function extractDependencies($module, $modules)
{
if (!array_key_exists('dependencies', $module->info)) {
return [];
}

$dependencies = [];
foreach ($module->info['dependencies'] as $dependency) {
$dependencyExploded = explode(':', $dependency);
$moduleDependency = count($dependencyExploded)>1?$dependencyExploded[1]:$dependencyExploded[0];
if ($space = strpos($moduleDependency, ' ')) {
$moduleDependency = substr($moduleDependency, 0, $space);
}

if (!in_array($moduleDependency, $modules)) {
continue;
}

if ($moduleDependency !== $module->getName()) {
$dependencies[$moduleDependency] = 'drupal/'.$moduleDependency;
}
}

return $dependencies;
}

private function calculateVersion($version)
{
$replaceKeys = [
'8.x-' => '',
'8.' => ''
];
return str_replace(
array_keys($replaceKeys),
array_values($replaceKeys),
$version
);
}
}

0 comments on commit 268569a

Please sign in to comment.