├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── composer.json
├── phpunit.xml.dist
├── src
├── CommandProvider.php
├── ComposerPlugin.php
└── DrupalInitCommand.php
└── tests
└── DrupalInitCommandTest.php
/.gitignore:
--------------------------------------------------------------------------------
1 | composer.lock
2 | composer.phar
3 | /vendor/
4 | /build/
5 |
6 | /.idea/
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | # - 5.5
5 | # - 5.6
6 | # - 7.0
7 | - 7.1
8 |
9 | # This triggers builds to run on the new TravisCI infrastructure.
10 | # See: http://docs.travis-ci.com/user/workers/container-based-infrastructure/
11 | sudo: false
12 |
13 | before_script:
14 | - travis_retry composer self-update
15 | - travis_retry composer install --no-interaction --prefer-dist --dev
16 |
17 | script:
18 | - composer test
19 | # - vendor/bin/phpunit --coverage-text --coverage-clover=coverage.clover
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 hussainweb
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # drupal-composer-init
2 |
3 | [](https://github.com/hussainweb/drupal-composer-init/releases)
4 | [](LICENSE.md)
5 | [](https://travis-ci.org/hussainweb/drupal-composer-init)
6 | [](https://packagist.org/packages/hussainweb/drupal-composer-init)
7 |
8 | This plugin provides a new composer command (`drupal-init`) which helps in creating new Drupal installations based on composer. Most of the options are very similar to the default `composer init` command. There are additional options to specify a Drupal core or distro to use and the docroot.
9 |
10 | This plugin also supports Drupal 7 installation but this option needs to be passed in from command line.
11 |
12 | The composer.json setup that this plugin generates is inspired by [drupal-composer/drupal-project](https://github.com/drupal-composer/drupal-project) (both D7 and D8 versions). One important difference is that the composer.json generated by this command does not need several scripts which are part of the drupal-composer project. All the functionality is moved to [hussainweb/drupal-composer-helper](https://github.com/hussainweb/drupal-composer-helper). There are additional benefits like a simpler `extra` section and a more maintainable installation. For more details, see the [drupal-composer-helper](https://github.com/hussainweb/drupal-composer-helper) plugin.
13 |
14 | ## Installation
15 |
16 | Since this plugin provides a new composer command that should be used in an empty directory (or at least a directory without a composer.json setup), this has to be installed globally.
17 |
18 | ```
19 | composer global require hussainweb/drupal-composer-init:~1.0
20 | ```
21 |
22 | ## Updating
23 |
24 | ```
25 | composer global update hussainweb/drupal-composer-init --with-dependencies
26 | ```
27 |
28 | ## Usage
29 |
30 | In a fresh directory, run this command to get started.
31 |
32 | ```
33 | composer drupal-init
34 | ```
35 |
36 | To intialise a Drupal 7 website, run the following command:
37 |
38 | ```
39 | composer drupal-init --drupal-7
40 | ```
41 |
42 | ### Specifying extensions (modules, themes, profiles)
43 |
44 | Drupal extensions such as modules, themes, and profiles can be specified in the regular `require` or `require-dev` section of composer.json schema.
45 |
46 | All Drupal extensions can be specified in the regular packages section with their drupal.org name prefixed by '`drupal/`'. For example, if you want to require panels module, specify `drupal/panels`.
47 |
48 | ```
49 | Define your dependencies.
50 |
51 | Would you like to define your dependencies (require) now [yes]?
52 | Search for a package: drupal/panels
53 | Enter the version constraint to require (or leave blank to use the latest version):
54 | Using version ^4.2 for drupal/panels
55 | Search for a package: drupal/redirect
56 | Enter the version constraint to require (or leave blank to use the latest version):
57 | Using version ^1.0@beta for drupal/redirect
58 | Search for a package:
59 | ```
60 |
61 | ### Additional Help
62 |
63 | Run `composer help drupal-init` for more options.
64 |
65 | ```
66 | Usage:
67 | drupal-init [options]
68 |
69 | Options:
70 | --name=NAME Name of the package
71 | --description=DESCRIPTION Description of package
72 | --author=AUTHOR Author name of package
73 | --type[=TYPE] Type of package (e.g. library, project, metapackage, composer-plugin) [default: "project"]
74 | --homepage=HOMEPAGE Homepage of package
75 | --require=REQUIRE Package to require with a version constraint, e.g. foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0" (multiple values allowed)
76 | --require-dev=REQUIRE-DEV Package to require for development with a version constraint, e.g. foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0" (multiple values allowed)
77 | -c, --core=CORE Drupal Core or distribution, e.g. drupal/core or acquia/lightning [default: "drupal/core"]
78 | -s, --stability=STABILITY Minimum stability (empty or one of: stable, RC, beta, alpha, dev)
79 | -l, --license=LICENSE License of package
80 | --repository=REPOSITORY Add custom repositories, either by URL or using JSON arrays (multiple values allowed)
81 | -w, --web-dir=WEB-DIR Specify the docroot (defaults to web) [default: "web"]
82 | --drupal-7 Use Drupal 7 packagist instead of Drupal 8
83 | -h, --help Display this help message
84 | -q, --quiet Do not output any message
85 | -V, --version Display this application version
86 | --ansi Force ANSI output
87 | --no-ansi Disable ANSI output
88 | -n, --no-interaction Do not ask any interactive question
89 | --profile Display timing and memory usage information
90 | --no-plugins Whether to disable plugins.
91 | -d, --working-dir=WORKING-DIR If specified, use the given directory as working directory.
92 | -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
93 |
94 | Help:
95 | The drupal-init command creates a composer.json file
96 | usable for Drupal projects in the current directory.
97 |
98 | php composer.phar drupal-init
99 | ```
100 |
101 | ## Contributing
102 |
103 | Contributions are welcome. Please use the issue queue to describe the problem. Pull requests are welcome.
104 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hussainweb/drupal-composer-init",
3 | "description": "Initialise a Drupal composer project setup",
4 | "type": "composer-plugin",
5 | "keywords": [
6 | "drupal"
7 | ],
8 | "license": "MIT",
9 | "authors": [
10 | {
11 | "name": "hussainweb",
12 | "email": "hussainweb@gmail.com",
13 | "homepage": "http://hussainweb.me",
14 | "role": "Developer"
15 | }
16 | ],
17 | "require": {
18 | "php": ">=5.5.9",
19 | "composer-plugin-api": "^1.1"
20 | },
21 | "require-dev": {
22 | "composer/composer": "~1.0",
23 | "phpunit/phpunit": "^5.7",
24 | "squizlabs/php_codesniffer": "~2.3"
25 | },
26 | "autoload": {
27 | "psr-4": {
28 | "Hussainweb\\DrupalComposerInit\\": "src/"
29 | }
30 | },
31 | "autoload-dev": {
32 | "psr-4": {
33 | "Hussainweb\\DrupalComposerInit\\": "tests/"
34 | }
35 | },
36 | "config": {
37 | "optimize-autoloader": true,
38 | "sort-packages": true
39 | },
40 | "extra": {
41 | "branch-alias": {
42 | "dev-master": "1.x-dev"
43 | },
44 | "class": "Hussainweb\\DrupalComposerInit\\ComposerPlugin"
45 | },
46 | "scripts": {
47 | "test": [
48 | "composer validate --no-interaction",
49 | "phpcs --standard=psr2 src/ tests/",
50 | "phpunit tests/"
51 | ]
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 | tests
15 |
16 |
17 |
18 |
19 | src/
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/CommandProvider.php:
--------------------------------------------------------------------------------
1 | 'Hussainweb\DrupalComposerInit\CommandProvider',
27 | ];
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/DrupalInitCommand.php:
--------------------------------------------------------------------------------
1 | setName('drupal-init')
26 | ->setDescription('Creates a Drupal composer.json file in current directory.')
27 | ->setDefinition([
28 | new InputOption('name', null, InputOption::VALUE_REQUIRED, 'Name of the package'),
29 | new InputOption('description', null, InputOption::VALUE_REQUIRED, 'Description of package'),
30 | new InputOption('author', null, InputOption::VALUE_REQUIRED, 'Author name of package'),
31 | // new InputOption('version', null, InputOption::VALUE_NONE, 'Version of package'),
32 | new InputOption('type', null, InputOption::VALUE_OPTIONAL, 'Type of package (e.g. library, project, metapackage, composer-plugin)', 'project'),
33 | new InputOption('homepage', null, InputOption::VALUE_REQUIRED, 'Homepage of package'),
34 | new InputOption('require', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Package to require with a version constraint, e.g. foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"'),
35 | new InputOption('require-dev', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Package to require for development with a version constraint, e.g. foo/bar:1.0.0 or foo/bar=1.0.0 or "foo/bar 1.0.0"'),
36 | new InputOption('core', 'c', InputOption::VALUE_REQUIRED, 'Drupal Core or distribution, e.g. drupal/core or acquia/lightning', 'drupal/core'),
37 | new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: '.implode(', ', array_keys(BasePackage::$stabilities)).')'),
38 | new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'),
39 | new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories, either by URL or using JSON arrays'),
40 | new InputOption('web-dir', 'w', InputOption::VALUE_REQUIRED, 'Specify the docroot (defaults to web)', 'web'),
41 | new InputOption('drupal-7', null, InputOption::VALUE_NONE, 'Use Drupal 7 packagist instead of Drupal 8'),
42 | // new InputOption('extensions', 'm', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Extensions (such as modules or themes) to require with a version constraint, e.g. panels:^4.0'),
43 | // new InputOption('extensions-dev', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'Extensions (such as modules or themes) to require for development with a version constraint, e.g. panels:^4.0'),
44 | ])
45 | ->setHelp(<<drupal-init command creates a composer.json file
47 | usable for Drupal projects in the current directory.
48 |
49 | php composer.phar drupal-init
50 |
51 | EOT
52 | );
53 | // @codingStandardsIgnoreEnd
54 | }
55 |
56 | protected function isDrupal7(InputInterface $input)
57 | {
58 | return $input->getOption('drupal-7');
59 | }
60 |
61 | protected function getExtraRequires(InputInterface $input)
62 | {
63 | $requires = [
64 | 'd7' => [
65 | 'php >=5.2.5',
66 | 'ext-gd *',
67 | 'ext-xml *',
68 | 'ext-json *',
69 | 'ext-openssl *',
70 | 'ext-curl *',
71 | 'ext-pdo *',
72 | 'ext-pdo_mysql *',
73 | 'cweagans/composer-patches ^1.6.0',
74 | 'hussainweb/drupal-composer-helper ^1.0-beta3',
75 | 'drupal-composer/preserve-paths ^0.1',
76 | $input->getOption('core'),
77 | 'drupal/composer_autoloader ^1.0',
78 | 'drush/drush ~8.0',
79 | ],
80 | 'd8' => [
81 | 'cweagans/composer-patches ^1.6.0',
82 | 'hussainweb/drupal-composer-helper ^1.0',
83 | $input->getOption('core'),
84 | 'drupal/console ^1.0.2',
85 | 'drush/drush ~8.0|^9.0.0-beta8',
86 | ],
87 | ];
88 | return $this->isDrupal7($input) ? $requires['d7'] : $requires['d8'];
89 | }
90 |
91 | protected function getExtraRequireDevs(InputInterface $input)
92 | {
93 | $require_dev = [
94 | 'behat/mink ~1.7',
95 | 'behat/mink-goutte-driver ~1.2',
96 | 'jcalderonzumba/gastonjs ~1.0.2',
97 | 'jcalderonzumba/mink-phantomjs-driver ~0.3.1',
98 | 'mikey179/vfsstream ~1.2',
99 | 'phpunit/phpunit >=4.8.28 <5',
100 | 'symfony/css-selector ~2.8',
101 | ];
102 | return $this->isDrupal7($input) ? [] : $require_dev;
103 | }
104 |
105 | protected function execute(InputInterface $input, OutputInterface $output)
106 | {
107 | $options = $input->getOptions();
108 |
109 | $options['require'] = array_merge($this->getExtraRequires($input), $options['require']);
110 |
111 | $options['require-dev'] = array_merge($this->getExtraRequireDevs($input), $options['require-dev']);
112 |
113 | $input->setOption('require', $options['require']);
114 | $input->setOption('require-dev', $options['require-dev']);
115 | $input->setOption('type', 'project');
116 |
117 | $status = parent::execute($input, $output);
118 |
119 | if (!$status) {
120 | $web_prefix = $input->getOption('web-dir');
121 |
122 | // Write extra to composer.json file.
123 | $file = new JsonFile(Factory::getComposerFile());
124 | $options = $file->read();
125 | $options['extra'] = [
126 | 'drupal-composer-helper' => [
127 | 'web-prefix' => $web_prefix,
128 | ],
129 | 'enable-patching' => true,
130 | 'installer-paths' => [
131 | $web_prefix . '/core' => [
132 | 'type:drupal-core',
133 | ],
134 | ],
135 | ];
136 | $options['prefer-stable'] = true;
137 | $options['conflict'] = [
138 | 'drupal/drupal' => '*',
139 | ];
140 | $options['config'] = [
141 | 'sort-packages' => true,
142 | 'optimize-autoloader' => true,
143 | ];
144 |
145 | if ($this->isDrupal7($input)) {
146 | $extra = &$options['extra'];
147 | $options['conflict'] = [
148 | 'drupal/core' => '8.*',
149 | ];
150 |
151 | $extra['drupal-composer-helper']['set-d7-paths'] = true;
152 | $extra['preserve-paths'] = [
153 | $web_prefix . '/sites/all/libraries',
154 | $web_prefix . '/sites/all/modules/custom',
155 | $web_prefix . '/sites/all/modules/features',
156 | $web_prefix . '/sites/all/themes/custom',
157 | $web_prefix . '/sites/all/translations',
158 | $web_prefix . '/sites/default',
159 | ];
160 | $extra['installer-paths'][$web_prefix . '/'] = $extra['installer-paths'][$web_prefix . '/core'];
161 | unset($extra['installer-paths'][$web_prefix . '/core']);
162 | }
163 |
164 | $file->write($options);
165 | }
166 |
167 | return $status;
168 | }
169 |
170 | private function getRepositories(InputInterface $input)
171 | {
172 | $io = $this->getIO();
173 | // initialize repos if configured
174 | $config = Factory::createConfig($io);
175 | $repos = [new PlatformRepository()];
176 |
177 | $repositories = $input->getOption('repository');
178 | if ($repositories) {
179 | foreach ($repositories as $repo) {
180 | $repos[] = RepositoryFactory::fromString($io, $config, $repo);
181 | }
182 | }
183 |
184 | $packagist_url = 'https://packages.drupal.org/' . ($this->isDrupal7($input) ? '7' : '8');
185 | $repos[] = RepositoryFactory::createRepo($io, $config, [
186 | 'type' => 'composer',
187 | 'url' => $packagist_url,
188 | ]);
189 |
190 | // Add our Drupal packagist URL to the repositories so that it appears
191 | // in the composer.json file.
192 | $repositories[] = $packagist_url;
193 | $input->setOption('repository', $repositories);
194 |
195 | $repos[] = RepositoryFactory::createRepo($io, $config, [
196 | 'type' => 'composer',
197 | 'url' => 'https://packagist.org',
198 | ]);
199 |
200 | return new CompositeRepository($repos);
201 | }
202 |
203 | protected function interact(InputInterface $input, OutputInterface $output)
204 | {
205 | $git = $this->getGitConfig();
206 | $io = $this->getIO();
207 | /** @var \Symfony\Component\Console\Helper\FormatterHelper $formatter */
208 | $formatter = $this->getHelperSet()->get('formatter');
209 |
210 | $this->repos = $this->getRepositories($input);
211 |
212 | $io->writeError([
213 | '',
214 | $formatter->formatBlock('Welcome to the Drupal Composer config generator', 'bg=blue;fg=white', true),
215 | '',
216 | ]);
217 |
218 | // namespace
219 | $io->writeError([
220 | '',
221 | 'This command will guide you through creating your composer.json config for a Drupal setup.',
222 | '',
223 | ]);
224 |
225 | $cwd = realpath(".");
226 |
227 | if (!$name = $input->getOption('name')) {
228 | $name = basename($cwd);
229 | $name = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
230 | $name = strtolower($name);
231 | if (isset($git['github.user'])) {
232 | $name = $git['github.user'] . '/' . $name;
233 | } elseif (!empty($_SERVER['USERNAME'])) {
234 | $name = $_SERVER['USERNAME'] . '/' . $name;
235 | } elseif (!empty($_SERVER['USER'])) {
236 | $name = $_SERVER['USER'] . '/' . $name;
237 | } elseif (get_current_user()) {
238 | $name = get_current_user() . '/' . $name;
239 | } else {
240 | // package names must be in the format foo/bar
241 | $name = $name . '/' . $name;
242 | }
243 | $name = strtolower($name);
244 | } else {
245 | if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $name)) {
246 | throw new \InvalidArgumentException(
247 | 'The package name '.$name.' is invalid, it should be lowercase and have a
248 | vendor name, a forward slash, and a package name, matching: [a-z0-9_.-]+/[a-z0-9_.-]+'
249 | );
250 | }
251 | }
252 |
253 | $name = $io->askAndValidate(
254 | 'Package name (/) ['.$name.']: ',
255 | function ($value) use ($name) {
256 | if (null === $value) {
257 | return $name;
258 | }
259 |
260 | if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $value)) {
261 | throw new \InvalidArgumentException(
262 | 'The package name '.$value.' is invalid, it should be lowercase and have a
263 | vendor name, a forward slash, and a package name, matching: [a-z0-9_.-]+/[a-z0-9_.-]+'
264 | );
265 | }
266 |
267 | return $value;
268 | },
269 | null,
270 | $name
271 | );
272 | $input->setOption('name', $name);
273 |
274 | $description = $input->getOption('description') ?: false;
275 | $description = $io->ask(
276 | 'Description ['.$description.']: ',
277 | $description
278 | );
279 | $input->setOption('description', $description);
280 |
281 | if (null === $author = $input->getOption('author')) {
282 | if (isset($git['user.name']) && isset($git['user.email'])) {
283 | $author = sprintf('%s <%s>', $git['user.name'], $git['user.email']);
284 | }
285 | }
286 |
287 | $self = $this;
288 | $author = $io->askAndValidate(
289 | 'Author ['.$author.', n to skip]: ',
290 | function ($value) use ($self, $author) {
291 | if ($value === 'n' || $value === 'no') {
292 | return;
293 | }
294 | $value = $value ?: $author;
295 | $author = $self->parseAuthorString($value);
296 |
297 | return sprintf('%s <%s>', $author['name'], $author['email']);
298 | },
299 | null,
300 | $author
301 | );
302 | $input->setOption('author', $author);
303 |
304 | $minimumStability = $input->getOption('stability') ?: 'dev';
305 | $minimumStability = $io->askAndValidate(
306 | 'Minimum Stability ['.$minimumStability.']: ',
307 | function ($value) use ($self, $minimumStability) {
308 | if (null === $value) {
309 | return $minimumStability;
310 | }
311 |
312 | if (!isset(BasePackage::$stabilities[$value])) {
313 | throw new \InvalidArgumentException(
314 | 'Invalid minimum stability "'.$value.'". Must be empty or one of: '.
315 | implode(', ', array_keys(BasePackage::$stabilities))
316 | );
317 | }
318 |
319 | return $value;
320 | },
321 | null,
322 | $minimumStability
323 | );
324 | $input->setOption('stability', $minimumStability);
325 |
326 | $license = $input->getOption('license') ?: false;
327 | $license = $io->ask(
328 | 'License ['.$license.']: ',
329 | $license
330 | );
331 | $input->setOption('license', $license);
332 |
333 | $web_dir = $input->getOption('web-dir') ?: false;
334 | $web_dir = $io->ask(
335 | 'Public web directory ['.$web_dir.']: ',
336 | $web_dir
337 | );
338 | $input->setOption('web-dir', $web_dir);
339 |
340 | $input->setOption('core', $this->getCore($input));
341 |
342 | $io->writeError(['', 'Define your dependencies.', '']);
343 |
344 | $question = 'Would you like to define your dependencies (require) now [yes]? ';
345 | $require = $input->getOption('require');
346 | $requirements = [];
347 | if ($require || $io->askConfirmation($question, true)) {
348 | $requirements = $this->determineRequirements($input, $output, $require);
349 | }
350 | $input->setOption('require', $requirements);
351 |
352 | $question = 'Would you like to define your dev dependencies (require-dev) now [yes]? ';
353 | $requireDev = $input->getOption('require-dev');
354 | $devRequirements = [];
355 | if ($requireDev || $io->askConfirmation($question, true)) {
356 | $devRequirements = $this->determineRequirements($input, $output, $requireDev);
357 | }
358 | $input->setOption('require-dev', $devRequirements);
359 | }
360 |
361 | protected function getCore(InputInterface $input)
362 | {
363 | $io = $this->getIO();
364 |
365 | $core = $input->getOption('core');
366 | if ($this->isDrupal7($input) && $core == 'drupal/core') {
367 | $core = 'drupal/drupal';
368 | }
369 | $name_version_pair = $this->normalizeRequirements((array) $core);
370 | $core_package = $name_version_pair[0]['name'];
371 |
372 | $core_package = $io->askAndValidate(
373 | 'Drupal core or distribution ['.$core_package.']: ',
374 | function ($value) {
375 | $packages = $this->findPackages($value);
376 | foreach ($packages as $package) {
377 | if ($package['name'] == $value) {
378 | return $value;
379 | }
380 | }
381 | throw new \Exception('Package not found');
382 | },
383 | null,
384 | $core_package
385 | );
386 |
387 | $pool = new Pool($input->getOption('stability'));
388 | $pool->addRepository($this->getRepos());
389 | $versionSelector = new VersionSelector($pool);
390 | $package = $versionSelector->findBestCandidate($core_package);
391 | $core_version = $package ? $versionSelector->findRecommendedRequireVersion($package) : '';
392 |
393 | $core_version = $io->ask(
394 | 'Version for '.$core_package.' ['.$core_version.']: ',
395 | $core_version
396 | );
397 |
398 | return $core_package.' '.$core_version;
399 | }
400 | }
401 |
--------------------------------------------------------------------------------
/tests/DrupalInitCommandTest.php:
--------------------------------------------------------------------------------
1 | cwd = getcwd();
26 | chdir('/tmp');
27 | }
28 |
29 | protected function tearDown()
30 | {
31 | chdir($this->cwd);
32 | gc_collect_cycles();
33 | }
34 |
35 | protected function getHelperSet()
36 | {
37 | if ($this->helperSet === null) {
38 | $this->helperSet = new HelperSet([
39 | new FormatterHelper(),
40 | new QuestionHelper(),
41 | ]);
42 | }
43 | return $this->helperSet;
44 | }
45 |
46 | public function testDefaultInit()
47 | {
48 | $command = $this->getMockBuilder(DrupalInitCommand::class)
49 | ->setMethods([
50 | 'getCore',
51 | 'getHelperSet',
52 | ])
53 | ->getMock();
54 | $command->method('getCore')->willReturn('drupal/core ^8.4');
55 | $command->method('getHelperSet')->willReturn($this->getHelperSet());
56 |
57 | $tester = new CommandTester($command);
58 | $tester->execute([
59 | '--name' => 'test/test',
60 | '--author' => 'Test User ',
61 | '--description' => 'Test Description',
62 | '--core' => 'drupal/core ^8.4',
63 | '--stability' => 'dev',
64 | ]);
65 |
66 | $json = json_decode(file_get_contents('./composer.json'), true);
67 |
68 | $this->assertSame('test/test', $json['name']);
69 | $this->assertCount(1, $json['authors']);
70 | $this->assertSame('Test User', $json['authors'][0]['name']);
71 | $this->assertSame('testuser@example.com', $json['authors'][0]['email']);
72 | $this->assertSame('Test Description', $json['description']);
73 | $this->assertSame('project', $json['type']);
74 | $this->assertSame('dev', $json['minimum-stability']);
75 | $this->assertSame('composer', $json['repositories'][0]['type']);
76 | $this->assertSame('https://packages.drupal.org/8', $json['repositories'][0]['url']);
77 |
78 | $this->assertSame('web', $json['extra']['drupal-composer-helper']['web-prefix']);
79 |
80 | // @todo: Remove this test once the workaround for drupal-finder is fixed.
81 | $this->assertSame('type:drupal-core', $json['extra']['installer-paths']['web/core'][0]);
82 |
83 | $this->assertArrayNotHasKey('preserve-paths', $json['extra']);
84 |
85 | $this->assertArraySubset([
86 | 'hussainweb/drupal-composer-helper' => '^1.0',
87 | 'drupal/core' => '^8.4',
88 | ], $json['require']);
89 |
90 | unlink('./composer.json');
91 | }
92 |
93 | public function testDrupal7Mode()
94 | {
95 | $command = $this->getMockBuilder(DrupalInitCommand::class)
96 | ->setMethods([
97 | 'getCore',
98 | 'getHelperSet',
99 | ])
100 | ->getMock();
101 | $command->method('getCore')->willReturn('drupal/drupal ~7.0');
102 | $command->method('getHelperSet')->willReturn($this->getHelperSet());
103 |
104 | $tester = new CommandTester($command);
105 | $tester->execute([
106 | '--name' => 'test/test',
107 | '--author' => 'Test User ',
108 | '--description' => 'Test Description',
109 | '--core' => 'drupal/drupal ~7.0',
110 | '--stability' => 'dev',
111 | '--drupal-7' => true,
112 | ]);
113 |
114 | $json = json_decode(file_get_contents('./composer.json'), true);
115 |
116 | $this->assertSame('test/test', $json['name']);
117 | $this->assertCount(1, $json['authors']);
118 | $this->assertSame('Test User', $json['authors'][0]['name']);
119 | $this->assertSame('testuser@example.com', $json['authors'][0]['email']);
120 | $this->assertSame('Test Description', $json['description']);
121 | $this->assertSame('project', $json['type']);
122 | $this->assertSame('dev', $json['minimum-stability']);
123 | $this->assertSame('composer', $json['repositories'][0]['type']);
124 | $this->assertSame('https://packages.drupal.org/7', $json['repositories'][0]['url']);
125 |
126 | $this->assertSame('web', $json['extra']['drupal-composer-helper']['web-prefix']);
127 |
128 | // @todo: Remove this test once the workaround for drupal-finder is fixed.
129 | $this->assertSame('type:drupal-core', $json['extra']['installer-paths']['web/'][0]);
130 | $this->assertArrayNotHasKey('web/core', $json['extra']['installer-paths']);
131 |
132 | $this->assertArrayHasKey('preserve-paths', $json['extra']);
133 |
134 | $this->assertArrayNotHasKey('drupal/core', $json['require']);
135 | $this->assertArraySubset([
136 | 'drupal/drupal' => '~7.0',
137 | ], $json['require']);
138 |
139 | unlink('./composer.json');
140 | }
141 | }
142 |
--------------------------------------------------------------------------------