diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000000..60581237b1
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,27 @@
+#
+# Copy and rename this file to .env at root of this project.
+#
+
+# A common use case is to supply database creds via the environment. Edit settings.php
+# like so:
+#
+# $databases['default']['default'] = [
+# 'database' => getenv('MYSQL_DATABASE'),
+# 'driver' => 'mysql',
+# 'host' => getenv('MYSQL_HOSTNAME'),
+# 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
+# 'password' => getenv('MYSQL_PASSWORD'),
+# 'port' => getenv('MYSQL_PORT'),
+# 'prefix' => '',
+# 'username' => getenv('MYSQL_USER'),
+# ];
+#
+# Uncomment and populate as needed.
+# MYSQL_DATABASE=
+# MYSQL_HOSTNAME=
+# MYSQL_PASSWORD=
+# MYSQL_PORT=
+# MYSQL_USER=
+
+# Another common use case is to set Drush's --uri via environment.
+# DRUSH_OPTIONS_URI=http://example.com
diff --git a/.gitignore b/.gitignore
index 181eef61dc..50d278d8f4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,13 +1,24 @@
# Ignore directories generated by Composer
-drush/contrib
-vendor
-web/core
-web/modules/contrib
-web/themes/contrib
-web/profiles/contrib
+/drush/contrib/
+/vendor/
+/web/core/
+/web/modules/contrib/
+/web/themes/contrib/
+/web/profiles/contrib/
+/web/libraries/
+
+# Ignore sensitive information
+/web/sites/*/settings.php
+/web/sites/*/settings.local.php
# Ignore Drupal's file directory
-web/sites/default/files
+/web/sites/*/files/
+
+# Ignore SimpleTest multi-site environment.
+/web/sites/simpletest
# Ignore files generated by PhpStorm
-.idea
+/.idea/
+
+# Ignore .env files as they are personal
+/.env
diff --git a/.travis.yml b/.travis.yml
index fda43a5403..ac51e49242 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,36 +1,40 @@
language: php
+dist: trusty
+sudo: false
+
php:
- - 5.5
- - 5.6
- 7.0
-
-sudo: false
+ - 7.1
+ - 7.2
+ - 7.3
env:
global:
- SIMPLETEST_DB=sqlite://tmp/site.sqlite
- SIMPLETEST_BASE_URL="http://127.0.0.1:8080"
matrix:
- - RELEASE=stable
- - RELEASE=dev
+ - RELEASE=stable COMPOSER_CHANNEL=stable
+ - RELEASE=dev COMPOSER_CHANNEL=stable
+ - RELEASE=stable COMPOSER_CHANNEL=snapshot
before_install:
- echo 'sendmail_path = /bin/true' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
- phpenv config-rm xdebug.ini
- - composer --verbose self-update
+ - composer --verbose self-update --$COMPOSER_CHANNEL
- composer --version
install:
+ - composer --verbose validate
- composer --verbose install
script:
- - if [[ $RELEASE = dev ]]; then composer --verbose require --no-update drupal/core:8.0.x-dev; fi;
+ - if [[ $RELEASE = dev ]]; then composer --verbose remove --no-update drupal/console; fi;
+ - if [[ $RELEASE = dev ]]; then composer --verbose require --no-update drupal/core:8.8.x-dev; composer --verbose require --no-update --dev drupal/core-dev:8.8.x-dev; fi;
- if [[ $RELEASE = dev ]]; then composer --verbose update; fi;
- - cd $TRAVIS_BUILD_DIR/web
- - ./../vendor/bin/drush site-install --verbose --yes --db-url=sqlite://tmp/site.sqlite
- - ./../vendor/bin/drush runserver http://127.0.0.1:8080 &
- - sleep 3
- # Skip core/tests/Drupal/Tests/ComposerIntegrationTest.php because web/ has no composer.json
- - ./../vendor/bin/phpunit -c core --exclude-group Composer
- - ./../vendor/bin/drush
- - ./../vendor/bin/drupal
+ - ./vendor/bin/drush site-install --verbose --yes --db-url=sqlite://tmp/site.sqlite
+ - ./vendor/bin/drush runserver $SIMPLETEST_BASE_URL &
+ - until curl -s $SIMPLETEST_BASE_URL; do true; done > /dev/null
+ # Run a single unit test to verfiy the testing setup.
+ - ./vendor/bin/phpunit -c ./web/core ./web/core/modules/system/tests/src/Unit/SystemRequirementsTest.php
+ - ./vendor/bin/drush
+ - if [[ $RELEASE = stable ]]; then ./vendor/bin/drupal; fi;
diff --git a/README.md b/README.md
index 09c369b6bd..2c40e4384f 100644
--- a/README.md
+++ b/README.md
@@ -2,11 +2,11 @@
[](https://travis-ci.org/drupal-composer/drupal-project)
-This project template should provide a kickstart for managing your site
+This project template provides a starter kit for managing your site
dependencies with [Composer](https://getcomposer.org/).
If you want to know how to use it as replacement for
-[Drush Make](https://github.com/drush-ops/drush/blob/master/docs/make.md) visit
+[Drush Make](https://github.com/drush-ops/drush/blob/8.x/docs/make.md) visit
the [Documentation on drupal.org](https://www.drupal.org/node/2471553).
## Usage
@@ -14,25 +14,25 @@ the [Documentation on drupal.org](https://www.drupal.org/node/2471553).
First you need to [install composer](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx).
> Note: The instructions below refer to the [global composer installation](https://getcomposer.org/doc/00-intro.md#globally).
-You might need to replace `composer` with `php composer.phar` (or similar)
+You might need to replace `composer` with `php composer.phar` (or similar)
for your setup.
After that you can create the project:
```
-composer create-project drupal-composer/drupal-project:8.x-dev some-dir --stability dev --no-interaction
+composer create-project drupal-composer/drupal-project:8.x-dev some-dir --no-interaction
```
-With `composer require ...` you can download new dependencies to your
+With `composer require ...` you can download new dependencies to your
installation.
```
cd some-dir
-composer require drupal/devel:8.*
+composer require drupal/devel:~1.0
```
-The `composer create-project` command passes ownership of all files to the
-project that is created. You should create a new git repository, and commit
+The `composer create-project` command passes ownership of all files to the
+project that is created. You should create a new git repository, and commit
all files not excluded by the .gitignore file.
## What does the template do?
@@ -46,32 +46,33 @@ When installing the given `composer.json` some tasks are taken care of:
* Theme (packages of type `drupal-theme`) will be placed in `web/themes/contrib/`
* Profiles (packages of type `drupal-profile`) will be placed in `web/profiles/contrib/`
* Creates default writable versions of `settings.php` and `services.yml`.
-* Creates `sites/default/files`-directory.
+* Creates `web/sites/default/files`-directory.
* Latest version of drush is installed locally for use at `vendor/bin/drush`.
* Latest version of DrupalConsole is installed locally for use at `vendor/bin/drupal`.
+* Creates environment variables based on your .env file. See [.env.example](.env.example).
## Updating Drupal Core
-This project will attempt to keep all of your Drupal Core files up-to-date; the
-project [drupal-composer/drupal-scaffold](https://github.com/drupal-composer/drupal-scaffold)
-is used to ensure that your scaffold files are updated every time drupal/core is
-updated. If you customize any of the "scaffolding" files (commonly .htaccess),
-you may need to merge conflicts if any of your modfied files are updated in a
+This project will attempt to keep all of your Drupal Core files up-to-date; the
+project [drupal/core-composer-scaffold](https://github.com/drupal/core-composer-scaffold)
+is used to ensure that your scaffold files are updated every time drupal/core is
+updated. If you customize any of the "scaffolding" files (commonly .htaccess),
+you may need to merge conflicts if any of your modified files are updated in a
new release of Drupal core.
Follow the steps below to update your core files.
-1. Run `composer update drupal/core`.
-1. Run `git diff` to determine if any of the scaffolding files have changed.
- Review the files for any changes and restore any customizations to
+1. Run `composer update drupal/core drupal/core-dev --with-dependencies` to update Drupal Core and its dependencies.
+2. Run `git diff` to determine if any of the scaffolding files have changed.
+ Review the files for any changes and restore any customizations to
`.htaccess` or `robots.txt`.
1. Commit everything all together in a single commit, so `web` will remain in
sync with the `core` when checking out branches or running `git bisect`.
-1. In the event that there are non-trivial conflicts in step 2, you may wish
- to perform these steps on a branch, and use `git merge` to combine the
- updated core files with your customized files. This facilitates the use
- of a [three-way merge tool such as kdiff3](http://www.gitshah.com/2010/12/how-to-setup-kdiff-as-diff-tool-for-git.html). This setup is not necessary if your changes are simple;
- keeping all of your modifications at the beginning or end of the file is a
+1. In the event that there are non-trivial conflicts in step 2, you may wish
+ to perform these steps on a branch, and use `git merge` to combine the
+ updated core files with your customized files. This facilitates the use
+ of a [three-way merge tool such as kdiff3](http://www.gitshah.com/2010/12/how-to-setup-kdiff-as-diff-tool-for-git.html). This setup is not necessary if your changes are simple;
+ keeping all of your modifications at the beginning or end of the file is a
good strategy to keep merges easy.
## Generate composer.json from existing project
@@ -83,25 +84,62 @@ that the generated `composer.json` might differ from this project's file.
## FAQ
-### Should I commit the contrib modules I download
+### Should I commit the contrib modules I download?
-Composer recommends **no**. They provide [argumentation against but also
+Composer recommends **no**. They provide [argumentation against but also
workrounds if a project decides to do it anyway](https://getcomposer.org/doc/faqs/should-i-commit-the-dependencies-in-my-vendor-directory.md).
+### Should I commit the scaffolding files?
+
+The [Drupal Composer Scaffold](https://github.com/drupal/core-composer-scaffold) plugin can download the scaffold files (like
+index.php, update.php, …) to the web/ directory of your project. If you have not customized those files you could choose
+to not check them into your version control system (e.g. git). If that is the case for your project it might be
+convenient to automatically run the drupal-scaffold plugin after every install or update of your project. You can
+achieve that by registering `@composer drupal:scaffold` as post-install and post-update command in your composer.json:
+
+```json
+"scripts": {
+ "post-install-cmd": [
+ "@composer drupal:scaffold",
+ "..."
+ ],
+ "post-update-cmd": [
+ "@composer drupal:scaffold",
+ "..."
+ ]
+},
+```
### How can I apply patches to downloaded modules?
-If you need to apply patches (depending on the project being modified, a pull
-request is often a better solution), you can do so with the
+If you need to apply patches (depending on the project being modified, a pull
+request is often a better solution), you can do so with the
[composer-patches](https://github.com/cweagans/composer-patches) plugin.
-To add a patch to drupal module foobar insert the patches section in the extra
+To add a patch to drupal module foobar insert the patches section in the extra
section of composer.json:
```json
"extra": {
"patches": {
"drupal/foobar": {
- "Patch description": "URL to patch"
+ "Patch description": "URL or local path to patch"
}
}
}
```
+### How do I switch from packagist.drupal-composer.org to packages.drupal.org?
+
+Follow the instructions in the [documentation on drupal.org](https://www.drupal.org/docs/develop/using-composer/using-packagesdrupalorg).
+
+### How do I specify a PHP version ?
+
+This project supports PHP 7.0 as minimum version (see [Drupal 8 PHP requirements](https://www.drupal.org/docs/8/system-requirements/drupal-8-php-requirements)), however it's possible that a `composer update` will upgrade some package that will then require PHP 7+.
+
+To prevent this you can add this code to specify the PHP version you want to use in the `config` section of `composer.json`:
+```json
+"config": {
+ "sort-packages": true,
+ "platform": {
+ "php": "7.0.33"
+ }
+},
+```
diff --git a/composer.json b/composer.json
index c877abd3a9..b29500cc0c 100644
--- a/composer.json
+++ b/composer.json
@@ -2,7 +2,7 @@
"name": "drupal-composer/drupal-project",
"description": "Project template for Drupal 8 projects with composer",
"type": "project",
- "license": "GPL-2.0+",
+ "license": "GPL-2.0-or-later",
"authors": [
{
"name": "",
@@ -12,54 +12,69 @@
"repositories": [
{
"type": "composer",
- "url": "https://packagist.drupal-composer.org"
+ "url": "https://packages.drupal.org/8"
}
],
"require": {
- "composer/installers": "^1.0.20",
- "drupal-composer/drupal-scaffold": "^1.3.1",
- "cweagans/composer-patches": "~1.0",
- "drupal/core": "~8.0",
- "drush/drush": "~8.0",
- "drupal/console": "~0.10"
+ "php": ">=7.0.8",
+ "composer/installers": "^1.2",
+ "cweagans/composer-patches": "^1.6.5",
+ "drupal/console": "^1.0.2",
+ "drupal/core": "^8.8.0",
+ "drupal/core-composer-scaffold": "^8.8.0",
+ "drush/drush": "^9.7.1 | ^10.0.0",
+ "vlucas/phpdotenv": "^4.0",
+ "webflo/drupal-finder": "^1.0.0",
+ "zaporylie/composer-drupal-optimizations": "^1.0"
},
"require-dev": {
- "behat/mink": "~1.6",
- "behat/mink-goutte-driver": "~1.2",
- "jcalderonzumba/gastonjs": "^1.1@dev",
- "jcalderonzumba/mink-phantomjs-driver": "~0.3.1",
- "mikey179/vfsStream": "~1.2",
- "phpunit/phpunit": "~4.8",
- "symfony/css-selector": "2.7.*"
+ "drupal/core-dev": "^8.8.0"
},
"conflict": {
"drupal/drupal": "*"
},
"minimum-stability": "dev",
"prefer-stable": true,
+ "config": {
+ "sort-packages": true
+ },
"autoload": {
"classmap": [
"scripts/composer/ScriptHandler.php"
- ]
+ ],
+ "files": ["load.environment.php"]
},
"scripts": {
- "drupal-scaffold": "DrupalComposer\\DrupalScaffold\\Plugin::scaffold",
+ "pre-install-cmd": [
+ "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
+ ],
+ "pre-update-cmd": [
+ "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
+ ],
"post-install-cmd": [
- "DrupalProject\\composer\\ScriptHandler::buildScaffold",
"DrupalProject\\composer\\ScriptHandler::createRequiredFiles"
],
"post-update-cmd": [
- "DrupalProject\\composer\\ScriptHandler::buildScaffold",
"DrupalProject\\composer\\ScriptHandler::createRequiredFiles"
]
},
"extra": {
+ "composer-exit-on-patch-failure": true,
+ "patchLevel": {
+ "drupal/core": "-p2"
+ },
+ "drupal-scaffold": {
+ "locations": {
+ "web-root": "web/"
+ }
+ },
"installer-paths": {
"web/core": ["type:drupal-core"],
+ "web/libraries/{$name}": ["type:drupal-library"],
"web/modules/contrib/{$name}": ["type:drupal-module"],
"web/profiles/contrib/{$name}": ["type:drupal-profile"],
"web/themes/contrib/{$name}": ["type:drupal-theme"],
- "drush/contrib/{$name}": ["type:drupal-drush"]
+ "drush/Commands/contrib/{$name}": ["type:drupal-drush"]
}
}
}
diff --git a/drush/Commands/PolicyCommands.php b/drush/Commands/PolicyCommands.php
new file mode 100644
index 0000000000..290b4e0331
--- /dev/null
+++ b/drush/Commands/PolicyCommands.php
@@ -0,0 +1,38 @@
+input()->getArgument('target') == '@prod') {
+ throw new \Exception(dt('Per !file, you may never overwrite the production database.', ['!file' => __FILE__]));
+ }
+ }
+
+ /**
+ * Limit rsync operations to production site.
+ *
+ * @hook validate core:rsync
+ *
+ * @throws \Exception
+ */
+ public function rsyncValidate(CommandData $commandData) {
+ if (preg_match("/^@prod/", $commandData->input()->getArgument('target'))) {
+ throw new \Exception(dt('Per !file, you may never rsync to the production site.', ['!file' => __FILE__]));
+ }
+ }
+}
diff --git a/drush/README.md b/drush/README.md
index 8c85c145d6..9d7bd397ad 100644
--- a/drush/README.md
+++ b/drush/README.md
@@ -1 +1 @@
-This directory contains commands, configuration and site aliases for Drush. See http://packages.drush.org/ for a directory of Drush commands installable via Composer.
+This directory contains commands, configuration and site aliases for Drush. See https://packagist.org/search/?type=drupal-drush for a directory of Drush commands installable via Composer.
diff --git a/drush/drush.yml b/drush/drush.yml
new file mode 100644
index 0000000000..a8cbd00730
--- /dev/null
+++ b/drush/drush.yml
@@ -0,0 +1,6 @@
+#
+# A Drush configuration file
+#
+# Docs at https://github.com/drush-ops/drush/blob/master/examples/example.drush.yml
+#
+# Edit or remove this file as needed.
diff --git a/drush/policy.drush.inc b/drush/policy.drush.inc
deleted file mode 100644
index 6a1242e5de..0000000000
--- a/drush/policy.drush.inc
+++ /dev/null
@@ -1,39 +0,0 @@
-safeLoad();
diff --git a/scripts/composer/ScriptHandler.php b/scripts/composer/ScriptHandler.php
index ab1dcda627..51026d38a1 100644
--- a/scripts/composer/ScriptHandler.php
+++ b/scripts/composer/ScriptHandler.php
@@ -8,24 +8,19 @@
namespace DrupalProject\composer;
use Composer\Script\Event;
+use Composer\Semver\Comparator;
+use Drupal\Core\Site\Settings;
+use DrupalFinder\DrupalFinder;
use Symfony\Component\Filesystem\Filesystem;
+use Webmozart\PathUtil\Path;
class ScriptHandler {
- protected static function getDrupalRoot($project_root) {
- return $project_root . '/web';
- }
-
- public static function buildScaffold(Event $event) {
- $fs = new Filesystem();
- if (!$fs->exists(static::getDrupalRoot(getcwd()) . '/autoload.php')) {
- \DrupalComposer\DrupalScaffold\Plugin::scaffold($event);
- }
- }
-
public static function createRequiredFiles(Event $event) {
$fs = new Filesystem();
- $root = static::getDrupalRoot(getcwd());
+ $drupalFinder = new DrupalFinder();
+ $drupalFinder->locateRoot(getcwd());
+ $drupalRoot = $drupalFinder->getDrupalRoot();
$dirs = [
'modules',
@@ -35,32 +30,70 @@ public static function createRequiredFiles(Event $event) {
// Required for unit testing
foreach ($dirs as $dir) {
- if (!$fs->exists($root . '/'. $dir)) {
- $fs->mkdir($root . '/'. $dir);
- $fs->touch($root . '/'. $dir . '/.gitkeep');
+ if (!$fs->exists($drupalRoot . '/'. $dir)) {
+ $fs->mkdir($drupalRoot . '/'. $dir);
+ $fs->touch($drupalRoot . '/'. $dir . '/.gitkeep');
}
}
// Prepare the settings file for installation
- if (!$fs->exists($root . '/sites/default/settings.php')) {
- $fs->copy($root . '/sites/default/default.settings.php', $root . '/sites/default/settings.php');
- $fs->chmod($root . '/sites/default/settings.php', 0666);
- $event->getIO()->write("Create a sites/default/settings.php file with chmod 0666");
- }
-
- // Prepare the services file for installation
- if (!$fs->exists($root . '/sites/default/services.yml')) {
- $fs->copy($root . '/sites/default/default.services.yml', $root . '/sites/default/services.yml');
- $fs->chmod($root . '/sites/default/services.yml', 0666);
- $event->getIO()->write("Create a sites/default/services.yml file with chmod 0666");
+ if (!$fs->exists($drupalRoot . '/sites/default/settings.php') && $fs->exists($drupalRoot . '/sites/default/default.settings.php')) {
+ $fs->copy($drupalRoot . '/sites/default/default.settings.php', $drupalRoot . '/sites/default/settings.php');
+ require_once $drupalRoot . '/core/includes/bootstrap.inc';
+ require_once $drupalRoot . '/core/includes/install.inc';
+ new Settings([]);
+ $settings['settings']['config_sync_directory'] = (object) [
+ 'value' => Path::makeRelative($drupalFinder->getComposerRoot() . '/config/sync', $drupalRoot),
+ 'required' => TRUE,
+ ];
+ drupal_rewrite_settings($settings, $drupalRoot . '/sites/default/settings.php');
+ $fs->chmod($drupalRoot . '/sites/default/settings.php', 0666);
+ $event->getIO()->write("Created a sites/default/settings.php file with chmod 0666");
}
// Create the files directory with chmod 0777
- if (!$fs->exists($root . '/sites/default/files')) {
+ if (!$fs->exists($drupalRoot . '/sites/default/files')) {
$oldmask = umask(0);
- $fs->mkdir($root . '/sites/default/files', 0777);
+ $fs->mkdir($drupalRoot . '/sites/default/files', 0777);
umask($oldmask);
- $event->getIO()->write("Create a sites/default/files directory with chmod 0777");
+ $event->getIO()->write("Created a sites/default/files directory with chmod 0777");
+ }
+ }
+
+ /**
+ * Checks if the installed version of Composer is compatible.
+ *
+ * Composer 1.0.0 and higher consider a `composer install` without having a
+ * lock file present as equal to `composer update`. We do not ship with a lock
+ * file to avoid merge conflicts downstream, meaning that if a project is
+ * installed with an older version of Composer the scaffolding of Drupal will
+ * not be triggered. We check this here instead of in drupal-scaffold to be
+ * able to give immediate feedback to the end user, rather than failing the
+ * installation after going through the lengthy process of compiling and
+ * downloading the Composer dependencies.
+ *
+ * @see https://github.com/composer/composer/pull/5035
+ */
+ public static function checkComposerVersion(Event $event) {
+ $composer = $event->getComposer();
+ $io = $event->getIO();
+
+ $version = $composer::VERSION;
+
+ // The dev-channel of composer uses the git revision as version number,
+ // try to the branch alias instead.
+ if (preg_match('/^[0-9a-f]{40}$/i', $version)) {
+ $version = $composer::BRANCH_ALIAS_VERSION;
+ }
+
+ // If Composer is installed through git we have no easy way to determine if
+ // it is new enough, just display a warning.
+ if ($version === '@package_version@' || $version === '@package_branch_alias_version@') {
+ $io->writeError('You are running a development version of Composer. If you experience problems, please update Composer to the latest stable version.');
+ }
+ elseif (Comparator::lessThan($version, '1.0.0')) {
+ $io->writeError('Drupal-project requires Composer version 1.0.0 or higher. Please update your Composer before continuing.');
+ exit(1);
}
}