diff --git a/.build-gitignore b/.build-gitignore
new file mode 100644
index 0000000000..894354c961
--- /dev/null
+++ b/.build-gitignore
@@ -0,0 +1,11 @@
+; Alternative .gitignore file which is used when commit build artifcats.
+.vagrant
+dumps
+npm-debug.log
+node_modules
+bower_components
+web/sites/default/settings.php
+web/sites/default/files
+web/sites/default/private
+web/files
+web/files-private
diff --git a/.defaults.env b/.defaults.env
new file mode 100644
index 0000000000..d7bdf3bb80
--- /dev/null
+++ b/.defaults.env
@@ -0,0 +1,17 @@
+# Some project-wide default variables.
+# The defaults are loaded via the dotenv loader and not written to the ".env" file. We do not write them to ".env" as
+# the variables may be overriden by the dotenv setup and ".env" variables must be final for docker-compose.
+INSTALL_PROFILE=minimal
+DEFAULT_LANGUAGE=en
+PERSISTENT_FILES_DIR=files
+URL_SCHEME=https
+APP_SECRET={{ secret }}
+APP_SECRET_LONG={{ secret_long }}
+BEHAT_WARMUP_REQUIRED_CONTENT=window.__NUXT__
+
+# Configure URLs via drunomics/multisite-request-matchers, see https://github.com/drunomics/multisite-request-matcher/
+APP_MULTISITE_DOMAIN_PREFIX_SEPARATOR="_"
+APP_SITE_VARIANT_SEPARATOR="--"
+APP_SITE_VARIANTS=""
+APP_DEFAULT_SITE=example
+APP_SITES="example"
diff --git a/.env-defaults b/.env-defaults
new file mode 100644
index 0000000000..02fa2be802
--- /dev/null
+++ b/.env-defaults
@@ -0,0 +1,7 @@
+# Defaults written to .env during phapp setup - should only contain defaults for docker-compose!
+
+# We cannot use .defaults.env since those variables might have overrides that are applied by the dotenv loader setup,
+# which docker-compose would not pick up. The defaults here should not be overridden in dotenv.
+# Note: This variables are *not* picked up by amazeeio's lagoon hosting, only by docker-compose!
+
+PHAPP_ENV_MYSQL_DEFAULT_PASSWORD={{ secret }}
diff --git a/.github/workflows/test-drupal-setup.yml b/.github/workflows/test-drupal-setup.yml
new file mode 100644
index 0000000000..c9aef1cacf
--- /dev/null
+++ b/.github/workflows/test-drupal-setup.yml
@@ -0,0 +1,50 @@
+name: Test drupal setup
+on:
+ repository_dispatch:
+ workflow_dispatch:
+ push:
+ branches:
+ - '6.**'
+ pull_request:
+ types: [opened, reopened]
+jobs:
+ test-drupal-setup:
+ name: Build and install drupal project
+ runs-on: ubuntu-latest
+ timeout-minutes: 10
+ steps:
+ - uses: actions/checkout@v2
+ - name: Setup PHP
+ run: |
+ sudo update-alternatives --set php /usr/bin/php7.4
+ - name: "Determine composer cache directory"
+ id: "determine-composer-cache-directory"
+ run: "echo \"::set-output name=directory::$(composer config cache-dir)\""
+ - name: "Cache dependencies installed with composer"
+ uses: actions/cache@v2.1.5
+ with:
+ path: "${{ steps.determine-composer-cache-directory.outputs.directory }}"
+ key: ${{ runner.os }}-composer-v1-${{ hashFiles('./composer.json') }}
+ restore-keys: |
+ ${{ runner.os }}-composer-v1
+ - name: Install docker-compose.
+ run: |
+ sudo rm /usr/local/bin/docker-compose
+ curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` > docker-compose
+ chmod +x docker-compose
+ sudo mv docker-compose /usr/local/bin
+ - name: Install composer dependencies.
+ run: |
+ composer config platform-check false
+ composer create-project
+ composer install
+ - name: Setup the environment
+ run: |
+ vendor/bin/phapp setup localdev
+ - name: Setup docker containers
+ run: |
+ export COMPOSE_DEFAULT_USER=$(id -u $USER)
+ docker-compose up -d
+ echo "Waiting for mysql to come up..." && docker-compose exec cli /bin/bash -c "while ! echo exit | nc mariadb 3306; do sleep 1; done" >/dev/null
+ docker-compose exec cli phapp install --no-build
+ curl -v http://example.project.localdev.space | grep "Drupal 9"
diff --git a/.gitignore b/.gitignore
index cf18fe4b20..1b62dd3e10 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,21 +1,43 @@
# Ignore directories generated by Composer
-/drush/contrib/
-/vendor/
+/drush/Commands/contrib
+/vendor
/web/core/
/web/modules/contrib/
+/web/modules/drunomics
/web/themes/contrib/
/web/profiles/contrib/
/web/libraries/
-# Ignore sensitive information
-/web/sites/*/settings.php
-/web/sites/*/settings.local.php
+# Ignore Drupal per-site environment setup.
+/files
+/web/files
+/web/sites/*/files
+/web/sites/*/files-private
-# Ignore Drupal's file directory
-/web/sites/*/files/
+# Ignore local overrides and modules.
+/web/sites/local.*
+/web/modules/local
+/web/themes/local
+/web/profiles/local
# Ignore SimpleTest multi-site environment.
/web/sites/simpletest
-# Ignore files generated by PhpStorm
-/.idea/
+# Ignore files generated by editors and IDEs.
+.idea
+.vscode
+
+# Ignore setup files.
+/docker-compose.overrides.aliases.yml
+/.*.env
+/.env
+/.env.local
+!.defaults.env
+/web/sites/default
+.vagrant
+node_modules
+
+# Ignore .DS_Store files (OSX)
+.DS_Store
+/.editorconfig
+/.gitattributes
diff --git a/.travis.yml b/.travis.yml
index 5477b6e6b2..e4412e2ad4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,40 +1,57 @@
language: php
-dist: trusty
-sudo: false
+sudo: required
php:
- - 5.6
- - 7.0
- - 7.1
+ - 7.4
+git:
+ depth: false
env:
global:
- - SIMPLETEST_DB=sqlite://tmp/site.sqlite
- - SIMPLETEST_BASE_URL="http://127.0.0.1:8080"
- matrix:
- - RELEASE=stable COMPOSER_CHANNEL=stable
- - RELEASE=dev COMPOSER_CHANNEL=stable
- - RELEASE=stable COMPOSER_CHANNEL=snapshot
+ - DOCKER_COMPOSE_VERSION=1.22.0
+ COMPOSER_MEMORY_LIMIT=-1
+addons:
+ apt:
+ packages:
+ - docker-ce
+# Cache Composer, NPM & Drush directories.
+cache:
+ directories:
+ - $HOME/.cache/composer
+ - $HOME/.npm
+ - $HOME/.drush/cache
+
+# Setup the environment.
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_CHANNEL
- - composer --version
+ # Be sure no mails are going out by disabling sendmail.
+ - echo sendmail_path=`which true` >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
+
+ # Upgrade docker compose.
+ - sudo rm /usr/local/bin/docker-compose
+ - curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
+ - chmod +x docker-compose
+ - sudo mv docker-compose /usr/local/bin
install:
- - composer --verbose install
+ # Update the git branch by composer and create a project.
+ - |
+ source scripts/util/get-branch.sh
+ export GIT_BRANCH=$GIT_BRANCH
+ export GIT_COMMIT=$(git rev-parse HEAD)
+ ./scripts/util/replace-vars.sh < tests/drupal-project/package.envsubst.json > tests/drupal-project/package.json
+ git fetch origin $GIT_BRANCH:$GIT_BRANCH
+ composer create-project drunomics/drupal-project:"dev-$GIT_BRANCH#$GIT_COMMIT" --no-install --repository=tests/drupal-project/package.json project
+ cd project && composer install && cd ../
script:
- - if [[ $RELEASE = dev ]]; then composer --verbose remove --no-update drupal/console; fi;
- - if [[ $RELEASE = dev ]]; then composer --verbose require --no-update drupal/core:8.4.x-dev drush/drush:9.0.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 $SIMPLETEST_BASE_URL &
- - until curl -s $SIMPLETEST_BASE_URL; do true; done > /dev/null
- # Skip core/tests/Drupal/Tests/ComposerIntegrationTest.php because web/ has no composer.json
- # Ignore PageCache group temporarily, @see https://www.drupal.org/node/2770673
- - ./../vendor/bin/phpunit -c core --testsuite unit --exclude-group Composer,DependencyInjection,PageCache
- - ./../vendor/bin/drush
- - if [[ $RELEASE = stable ]]; then ./../vendor/bin/drupal; fi;
+ - cd project && vendor/bin/phapp setup localdev
+ # Fix permissions in docker container by setting the right user.
+ - export COMPOSE_DEFAULT_USER=$(id -u $USER)
+ - docker-compose up -d
+ - echo "Waiting for mysql to come up..." && docker-compose exec cli /bin/bash -c "while ! echo exit | nc mariadb 3306; do sleep 1; done" >/dev/null
+ - docker-compose exec cli phapp install --no-build
+ - curl -v http://example.project.localdev.space | grep "Drupal 9"
+
+after_success:
+ - echo "SUCCESS!"
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 23cb790338..0000000000
--- a/LICENSE
+++ /dev/null
@@ -1,339 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- {description}
- Copyright (C) {year} {fullname}
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- {signature of Ty Coon}, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
diff --git a/README.md b/README.md
index 8810aab1f8..9683eb4b51 100644
--- a/README.md
+++ b/README.md
@@ -1,131 +1,69 @@
-# Composer template for Drupal projects
+# Composer template for drunomics Drupal projects
-[![Build Status](https://travis-ci.org/drupal-composer/drupal-project.svg?branch=8.x)](https://travis-ci.org/drupal-composer/drupal-project)
+[![Build Status](https://www.travis-ci.org/drunomics/drupal-project.svg?branch=6.x)](https://www.travis-ci.org/drunomics/drupal-project)
-This project template should provide a kickstart for managing your site
-dependencies with [Composer](https://getcomposer.org/).
+Builds upon https://github.com/drupal-composer/drupal-project.
-If you want to know how to use it as replacement for
-[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).
+## Version compatibility
+
+| Git branch/tag: | Drupal core: |
+|--- | --- |
+| 5.x | Drupal 8 |
+| 6.x | Drupal 9 |
## Usage
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
+// Last stable version:
+composer create-project drunomics/drupal-project:6.* PROJECT
+// Last development version:
+composer create-project drunomics/drupal-project:6.*@dev --stability dev PROJECT
```
-With `composer require ...` you can download new dependencies to your
+With `composer require ...` you can download new dependencies to your
installation.
```
-cd some-dir
+cd PROJECT
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?
-
-When installing the given `composer.json` some tasks are taken care of:
-
-* Drupal will be installed in the `web`-directory.
-* Autoloader is implemented to use the generated composer autoloader in `vendor/autoload.php`,
- instead of the one provided by Drupal (`web/vendor/autoload.php`).
-* Modules (packages of type `drupal-module`) will be placed in `web/modules/contrib/`
-* 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 `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`.
-
-## 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 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 --with-dependencies` to update Drupal Core and its dependencies.
-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
- `.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
- good strategy to keep merges easy.
-
-## Generate composer.json from existing project
-
-With using [the "Composer Generate" drush extension](https://www.drupal.org/project/composer_generate)
-you can now generate a basic `composer.json` file from an existing project. Note
-that the generated `composer.json` might differ from this project's file.
-
-
-## FAQ
-
-### Should I commit the contrib modules I download?
-
-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-scaffold](https://github.com/drupal-composer/drupal-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 `@drupal-scaffold` as post-install and post-update command in your composer.json:
-
-```json
-"scripts": {
- "drupal-scaffold": "DrupalComposer\\DrupalScaffold\\Plugin::scaffold",
- "post-install-cmd": [
- "@drupal-scaffold",
- "..."
- ],
- "post-update-cmd": [
- "@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
-[composer-patches](https://github.com/cweagans/composer-patches) plugin.
-
-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"
- }
- }
-}
-```
-### How do I switch from packagist.drupal-composer.org to packages.drupal.org?
+## Documentation overview
+
+The template builds upon [drupal-composer/drupal-project](https://github.com/drupal-composer/drupal-project).
+Please follow the README of https://github.com/drupal-composer/drupal-project
+for general documentation.
+
+## Optional features
+
+Some optional features can be enabled by setting some environment variables
+when creating the project. To set a variable, you can set the variable when
+invoking composer; e.g.:
+
+ VARIABLE=1 composer create-project drunomics/drupal-project PROJECT
+
+The following variables are supported:
+
+| Variable | Description | Default | Possible values |
+| -------- | ----------- | ------- | --------------- |
+| PROJECT_ADD_DEVSETUP_DOCKER | Whether the docker-devsetup should be added. | 1 | "1" or "0" |
+| PROJECT_ADD_DEVSETUP_DRUNOMICS | Whether the drunomics devsetup extensions should be added. | unset | "1" or unset |
+
+## Default variables
+
+Environment variables that can be configured project-wide are managed in
+`.defaults.env`. Refer to the prepared variables in the file for environment
+variables tha are already supported in the template.
-Follow the instructions in the [documentation on drupal.org](https://www.drupal.org/docs/develop/using-composer/using-packagesdrupalorg).
diff --git a/README.md.dist b/README.md.dist
new file mode 100644
index 0000000000..0dcaa45fe8
--- /dev/null
+++ b/README.md.dist
@@ -0,0 +1,165 @@
+# {{ project }}
+developed by drunomics GmbH, office@drunomics.com
+
+This project is maintained using composer. Please refer to the documentation provided at https://github.com/drupal-composer/drupal-project and https://www.drupal.org/node/2471553.
+
+## Prerequesites
+
+ * Install docker and [docker-compose](https://docs.docker.com/compose/install/) - use version 1.22.0 or later.
+
+ * Install phapp (see tools) - or use the project-local version if preferred:
+
+ composer install-phar-tools
+ export PATH=./vendor/bin/:$PATH
+
+ * If your user ID is not 1000, run the following commands to
+ automatically set a suitable environment variable on every startup:
+
+ # Check ID:
+ id -u $USER
+ # If not 1000, run:
+ echo "# Allow docker-compose setup to switch to the correct user." >> ~/.bashrc
+ echo "export COMPOSE_DEFAULT_USER=$(id -u $USER)" >> ~/.bashrc
+ bash
+
+## Project devsetup
+
+To setup the project, ensure you have all prerequesites fullfilled and follow next steps:
+
+ * Optional: Drop container and data from previous runs:
+
+ docker-compose down -v
+
+ * Initialize setup and run docker compose
+
+ phapp setup localdev
+ phapp build
+ docker-compose up -d --build
+
+* Build the app:
+
+ phapp build
+
+ * Run `phapp init` to quickly initialize the application.
+
+ docker-compose exec cli phapp init --no-build
+
+## Localdev project URLs
+
+| Url | Webroot | Description |
+| --- | ------- | ----------- |
+| http://example.{{ project }}.localdev.space/ | web | the Example site |
+
+## Docker-compose - IMPORTANT NOTES.
+
+For now most phapp and drush must be from inside the docker container.
+Do so via
+
+ docker-compose exec cli phapp init --no-build
+ docker-compose exec cli drush cr
+
+However, the exception is `phapp build`. Run it on the host so that your SSH key(s)
+are picked up and you can access private repositories:
+
+ phapp build
+
+During development it's convenient to permanently switch to the docker cli container:
+
+ docker-compose exec cli bash
+ drush cr
+
+## Command line tools
+
+### Phapp
+Version 0.6.7 or later is required. Either install it globally and run `phapp`
+or execute the embedded phapp version from the root repository directory:
+
+```./vendor/bin/phapp ```
+
+Refer to [the project page](http://github.com/drunomics/phapp-cli) for
+instructions on how to install phapp globally.
+
+### Drush
+ To run drush, execute from the root repository directory:
+ ```./vendor/bin/drush ```
+
+ The more convenient alternative is to install a global launcher or a global
+ drush with version 8, which includes a global launcher. Then, drush picks up
+ the project-local drush automatically.
+ For docs on drush see http://docs.drush.org/en/master/.
+
+## Useful commands
+
+- Commands for setting up or updating the project:
+
+```
+# Get in the docker web container (where you can use the phapp commands)
+docker-compose exec cli bash
+
+# Quick-install the application for development:
+docker-compose exec cli phapp init --no-build
+
+# Update the build and run updates after switching branches:
+phapp build
+docker-compose exec cli phapp update --no-build
+
+# Install the app from scratch:
+docker-compose exec cli phapp install
+```
+The commands executed can be found in `phapp.yml`.
+
+- During development, some useful commands are:
+
+```
+# Config export (export your config changes):
+docker-compose exec cli drush cex -y
+
+# Config import (manual import of config files):
+docker-compose exec cli drush cim -y
+
+# Cache clear/rebuild:
+docker-compose exec cli drush cr
+```
+
+## Running tests
+
+Tests are implemented using behat and use a headless chrome browser for javascript enabled tests:
+
+To run the tests:
+
+ ./tests/behat/run.sh
+
+Any further arguments are forwarded to behat:
+
+ ./tests/behat/run.sh --tags=javascript
+
+
+## Coding style
+
+To check the coding style for the project's custom code, run PHP code sniffer:
+
+ composer cs
+
+To automatically fix the coding style errors (as far as possible), run the PHP
+code beautifier:
+
+ composer cbf
+
+### Pre-commit checks
+
+Coding style can be checked automatically via Git's pre-commit hooks. To do so, just make sure to run the script `devsetup/setup-git-config.sh` at least once.
+
+Once configured, running pre-commit hooks can be bypassed via the Git commmit
+`--no-verify` option.
+
+### PHPstorm coding style configuration
+
+Configure the following settings:
+* Under Languages / PHP / Code Sniffer
+ - Select "local" configuration and make it point to `vendor/bin/phpcs`).
+* Under Editor / Inspections / PHP Code Sniffer validation:
+ - Select "warning" as severity.
+ - Show warnings as "warning"
+ - Show sniff name "true"
+ - Coding standard: "custom", make it point to the phpcs.xml.dist file in the
+ vcs root.
diff --git a/composer.json b/composer.json
index 407d3424fe..7daeafeb8e 100644
--- a/composer.json
+++ b/composer.json
@@ -1,75 +1,163 @@
{
- "name": "drupal-composer/drupal-project",
- "description": "Project template for Drupal 8 projects with composer",
+ "name": "drunomics/drupal-project",
+ "description": "Project template for drunomics Drupal 8 projects with composer",
"type": "project",
- "license": "GPL-2.0+",
+ "license": "GPL-2.0-or-later",
"authors": [
{
- "name": "",
- "role": ""
- }
- ],
- "repositories": [
- {
- "type": "composer",
- "url": "https://packages.drupal.org/8"
+ "name": "drunomics GmbH",
+ "role": "Creator."
}
],
"require": {
- "composer/installers": "^1.2",
- "cweagans/composer-patches": "^1.6",
- "drupal-composer/drupal-scaffold": "^2.2",
- "drupal/console": "^1.0.1",
- "drupal/core": "~8.0",
- "drush/drush": "~8.0",
- "webflo/drupal-finder": "^1.0.0",
- "webmozart/path-util": "^2.3"
+ "cweagans/composer-patches": "^1.7",
+ "drunomics/dsk-config-split": "^1.0",
+ "drunomics/multisite-request-matcher": "^1.7",
+ "drunomics/phapp_env_mode": "^1.1",
+ "drupal/admin_toolbar": "^2.0",
+ "drupal/core-composer-scaffold": "^9",
+ "drupal/core-recommended": "^9",
+ "drupal/services_env_parameter": "^1.2",
+ "drush/drush": "^10",
+ "oomphinc/composer-installers-extender": "^2.0",
+ "symfony/dotenv": "^3.4"
},
"require-dev": {
- "behat/mink": "~1.7",
- "behat/mink-goutte-driver": "~1.2",
- "jcalderonzumba/gastonjs": "~1.0.2",
- "jcalderonzumba/mink-phantomjs-driver": "~0.3.1",
- "mikey179/vfsstream": "~1.2",
- "phpunit/phpunit": ">=4.8.28 <5",
- "symfony/css-selector": "~2.8"
+ "behat/mink-goutte-driver": "^1.2",
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
+ "devinci/devinci-behat-extension": "^0.1",
+ "dmore/behat-chrome-extension": "^1.2",
+ "drunomics/behat-drupal-utils": "^2.9",
+ "drupal/coder": "^8.3",
+ "behat/behat": "^3.5",
+ "drupal/drupal-extension": "^4.1",
+ "drupal/core-dev": "^9"
},
"conflict": {
"drupal/drupal": "*"
},
+ "repositories": [
+ {
+ "type": "composer",
+ "url": "https://packages.drunomics.com"
+ },
+ {
+ "type": "composer",
+ "url": "https://packages.drupal.org/8"
+ },
+ {
+ "type": "composer",
+ "url": "https://asset-packagist.org"
+ }
+ ],
"minimum-stability": "dev",
"prefer-stable": true,
- "config": {
- "sort-packages": true
- },
"autoload": {
"classmap": [
- "scripts/composer/ScriptHandler.php"
- ]
+ "scripts/composer/CleanCommand.php",
+ "scripts/composer/PharInstaller.php"
+ ],
+ "files": ["dotenv/loader.php"]
},
"scripts": {
- "drupal-scaffold": "DrupalComposer\\DrupalScaffold\\Plugin::scaffold",
- "pre-install-cmd": [
- "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
+ "process-replacements": "php scripts/composer/process-replacements.php",
+ "install-phar-tools": [
+ "drunomics\\Composer\\PharInstaller::installPharTools"
+ ],
+ "init-setup": [
+ "@install-phar-tools"
],
- "pre-update-cmd": [
- "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
+ "post-root-package-install": [
+ "rm README.md && mv README.md.dist README.md",
+ "./scripts/init-devsetup-docker.sh && ./scripts/init-devsetup-drunomics.sh",
+ "@process-replacements",
+ "rm -rf tests/drupal-project .travis.yml"
],
- "post-install-cmd": [
- "DrupalProject\\composer\\ScriptHandler::createRequiredFiles"
+ "post-create-project-cmd": "@init-setup",
+ "post-install-cmd": "@init-setup",
+ "post-update-cmd": "@init-setup",
+ "clean": [
+ "drunomics\\Composer\\CleanCommand::runCommand"
],
- "post-update-cmd": [
- "DrupalProject\\composer\\ScriptHandler::createRequiredFiles"
- ]
+ "cs": "vendor/bin/phpcs --colors",
+ "cbf": "vendor/bin/phpcbf",
+ "check-security": "local-php-security-checker",
+ "test": "./tests/behat/run.sh --colors"
},
"extra": {
+ "drupal-scaffold": {
+ "file-mapping": {
+ "[web-root]/sites/development.services.yml": {
+ "mode": "skip"
+ },
+ "[web-root]/sites/example.settings.local.php": "web/sites/example.local.settings.php",
+ "[web-root]/sites/default/default.services.yml": {
+ "mode": "replace",
+ "path": "web/sites/all/services.yml",
+ "overwrite": false
+ },
+ "[web-root]/sites/example/default.settings.php": "web/core/assets/scaffold/files/default.settings.php"
+ },
+ "locations": {
+ "web-root": "web/"
+ }
+ },
+ "installer-types": ["drupal-library", "npm-asset", "bower-asset"],
"installer-paths": {
+ "drush/Commands/contrib/{$name}": ["type:drupal-drush"],
"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"]
+ "web/libraries/{$name}/": [
+ "type:drupal-library",
+ "type:npm-asset",
+ "type:bower-asset"
+ ],
+ "web/modules/drunomics/{$name}": ["vendor:drunomics"],
+ "web/modules/contrib/{$name}": ["type:drupal-module"]
+ },
+ "merge-plugin": {
+ "include": [
+ "web/modules/custom/*/composer.json"
+ ],
+ "recurse": false,
+ "replace": false,
+ "merge-extra": false
+ },
+ "tools": {
+ "phapp": {
+ "url": "https://github.com/drunomics/phapp-cli/releases/download/0.6.7/phapp.phar",
+ "version": "0.6.7"
+ },
+ "local-php-security-checker": {
+ "url": "https://github.com/fabpot/local-php-security-checker/releases/download/v1.0.0/local-php-security-checker_1.0.0_linux_amd64",
+ "version": "1.0.0"
+ }
+ },
+ "scripts-description": {
+ "clean": "Removes files of installed packages.",
+ "cs": "Run coding style checks using phpcs.",
+ "cbf": "Run coding style fixes using phpcbf.",
+ "check-security": "Verify only secure packages are installed.",
+ "install-phar-tools": "Installs phar tools used by this project.",
+ "test": "Run tests."
+ },
+ "enable-patching": true,
+ "composer-exit-on-patch-failure": true,
+ "patches": {}
+ },
+ "config": {
+ "platform": {
+ "php": "7.4"
+ },
+ "sort-packages": true,
+ "preferred-install": {
+ "drunomics/*": "source",
+ "*": "dist"
}
+ },
+ "suggest": {
+ "drunomics/dsk_media": "1.*",
+ "drunomics/dsk_devel": "1.*"
}
}
diff --git a/config/env/development/.htaccess b/config/env/development/.htaccess
new file mode 100644
index 0000000000..1238c0d2cb
--- /dev/null
+++ b/config/env/development/.htaccess
@@ -0,0 +1,23 @@
+# Deny all requests from Apache 2.4+.
+
+ Require all denied
+
+
+# Deny all requests from Apache 2.0-2.2.
+
+ Deny from all
+
+# Turn off all options we don't need.
+Options -Indexes -ExecCGI -Includes -MultiViews
+
+# Set the catch-all handler to prevent scripts from being executed.
+SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
+
+ # Override the handler again if we're run later in the evaluation list.
+ SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
+
+
+# If we know how to do it safely, disable the PHP engine entirely.
+
+ php_flag engine off
+
\ No newline at end of file
diff --git a/config/env/production/.htaccess b/config/env/production/.htaccess
new file mode 100644
index 0000000000..1238c0d2cb
--- /dev/null
+++ b/config/env/production/.htaccess
@@ -0,0 +1,23 @@
+# Deny all requests from Apache 2.4+.
+
+ Require all denied
+
+
+# Deny all requests from Apache 2.0-2.2.
+
+ Deny from all
+
+# Turn off all options we don't need.
+Options -Indexes -ExecCGI -Includes -MultiViews
+
+# Set the catch-all handler to prevent scripts from being executed.
+SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
+
+ # Override the handler again if we're run later in the evaluation list.
+ SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
+
+
+# If we know how to do it safely, disable the PHP engine entirely.
+
+ php_flag engine off
+
\ No newline at end of file
diff --git a/config/sync/.htaccess b/config/sync/.htaccess
new file mode 100644
index 0000000000..91883a339b
--- /dev/null
+++ b/config/sync/.htaccess
@@ -0,0 +1,23 @@
+# Deny all requests from Apache 2.4+.
+
+ Require all denied
+
+
+# Deny all requests from Apache 2.0-2.2.
+
+ Deny from all
+# Turn off all options we don't need.
+Options None
+Options +FollowSymLinks
+
+# Set the catch-all handler to prevent scripts from being executed.
+SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
+
+ # Override the handler again if we're run later in the evaluation list.
+ SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
+
+
+# If we know how to do it safely, disable the PHP engine entirely.
+
+ php_flag engine off
+
\ No newline at end of file
diff --git a/dotenv/dev.env b/dotenv/dev.env
new file mode 100644
index 0000000000..b7aa6a9692
--- /dev/null
+++ b/dotenv/dev.env
@@ -0,0 +1,3 @@
+PHAPP_ENV_TYPE=example
+PHAPP_ENV_MODE=production
+PHAPP_ENV_COLOR=215b4d
diff --git a/dotenv/drunomics-ci.env b/dotenv/drunomics-ci.env
new file mode 100644
index 0000000000..f342041e3a
--- /dev/null
+++ b/dotenv/drunomics-ci.env
@@ -0,0 +1,13 @@
+PHAPP_ENV_TYPE=drunomics-ci
+PHAPP_ENV_MODE=development
+PHAPP_ENV_COLOR=302f2f
+
+# Adjust available URLs while testing.
+# @see web/sites/sites.php
+
+# Note that CONTAINER_HOST gets defined via a generated .env file, see
+# scripts/setup-base.sh.
+APP_MULTISITE_DOMAIN=$CONTAINER_HOST
+
+ENV_UNIX_GROUP_WEBSERVER="www-data"
+BEHAT_CHROME_HOST=chrome-$CONTAINER_NAME
diff --git a/dotenv/live.env b/dotenv/live.env
new file mode 100644
index 0000000000..38b94edcb9
--- /dev/null
+++ b/dotenv/live.env
@@ -0,0 +1,3 @@
+PHAPP_ENV_TYPE=example
+PHAPP_ENV_MODE=production
+PHAPP_ENV_COLOR=aa3333
diff --git a/dotenv/loader.php b/dotenv/loader.php
new file mode 100644
index 0000000000..34c9dbf5cb
--- /dev/null
+++ b/dotenv/loader.php
@@ -0,0 +1,212 @@
+ $value) {
+ $vars .= "$variable=$value\n";
+ }
+ }
+
+ // Parse the site-specific dotenv files.
+ if (file_exists(__DIR__ . '/sites/all.env')) {
+ $vars .= file_get_contents(__DIR__ . '/sites/all.env') . "\n";
+ }
+ // Support per-environment all.env files.
+ if (file_exists(__DIR__ . '/sites/all.env-' . $phapp_env . '.env')) {
+ $vars .= file_get_contents(__DIR__ . '/sites/all.env-' . $phapp_env . '.env') . "\n";
+ }
+ if (file_exists(__DIR__ . '/sites/' . $site . '.env')) {
+ $vars .= file_get_contents(__DIR__ . '/sites/' . $site . '.env') . "\n";
+ }
+ return $vars;
+ }
+
+ /**
+ * Determines the currently active site.
+ *
+ * Copy of
+ * \drunomics\MultisiteRequestMatcher\RequestMatcher::determineActiveSite()
+ *
+ * @return string
+ * The active site's name.
+ */
+ public static function determineActiveSite() {
+ $site = getenv('SITE') ?: getenv('APP_DEFAULT_SITE');
+ if (!$site) {
+ $sites = explode(' ', getenv('APP_SITES'));
+ $site = reset($sites);
+ }
+ return $site;
+ }
+
+ /**
+ * Determines the currently active site variant.
+ *
+ * Copy of
+ * \drunomics\MultisiteRequestMatcher\RequestMatcher::determineActiveSiteVariant()
+ *
+ * @return string
+ * The active site variant, '' for the default variant.
+ */
+ public static function determineActiveSiteVariant() {
+ return getenv('SITE_VARIANT') ?: '';
+ }
+
+ /**
+ * Gets the same site variables as set during request matching.
+ *
+ * Copy of
+ * \drunomics\MultisiteRequestMatcher\RequestMatcher::getSiteVariables()
+ * to ensure it's available before vendors are installed.
+ */
+ public static function getSiteVariables($site = NULL, $site_variant = '') {
+ $site = $site ?: static::determineActiveSite();
+ $vars = [];
+ $vars['SITE'] = $site;
+ $vars['SITE_VARIANT'] = $site_variant ?: static::determineActiveSiteVariant();
+ if ($domain = getenv('APP_MULTISITE_DOMAIN')) {
+ $host = $site . getenv('APP_MULTISITE_DOMAIN_PREFIX_SEPARATOR') . $domain;
+ }
+ elseif (getenv('SITE') && getenv('APP_SITE_DOMAIN')) {
+ $host = getenv('APP_SITE_DOMAIN');
+ }
+ else {
+ $host = getenv('APP_SITE_DOMAIN__' . str_replace('-', '_', $site));
+ }
+ if ($vars['SITE_VARIANT']) {
+ $separator = getenv('APP_SITE_VARIANT_SEPARATOR') ?: '--';
+ $host = $vars['SITE_VARIANT'] . $separator . $host;
+ }
+ $vars['SITE_HOST'] = $host;
+ $vars['SITE_MAIN_HOST'] = $host;
+ return $vars;
+ }
+
+}
+
+// Allow using the loader via direct CLI execution.
+// @see loader.sh
+if (php_sapi_name() == "cli" && isset($argv[0]) && strpos($argv[0], '/loader.php') !== 0) {
+ if (!method_exists(PhappEnvironmentLoader::class, $argv[1])) {
+ die('Unable to find method ' . $argv[1]);
+ }
+ echo call_user_func(array(PhappEnvironmentLoader::class, $argv[1]));
+}
+// Else we are loaded via the composer autoloader.
+else {
+
+ // The following process must follow the same logic as loader.sh, but instead
+ // evaluating .env content with bash we use dotenv to parse it.
+ $dotenv = new Dotenv();
+ $dotenv->populate($dotenv->parse(PhappEnvironmentLoader::getDotenvFiles()));
+ $dotenv->populate($dotenv->parse(PhappEnvironmentLoader::determineEnvironment()));
+ if (!getenv('PHAPP_ENV')) {
+ die("Missing .env file or PHAPP_ENV environment variable. Did you run phapp setup?");
+ }
+ $dotenv->populate($dotenv->parse(PhappEnvironmentLoader::prepareDeterminedEnvironment()));
+
+ // Match the request and prepare site-specific dotenv vars.
+ $site = drunomics\MultisiteRequestMatcher\RequestMatcher::getInstance()
+ ->match();
+ $dotenv->populate($dotenv->parse(PhappEnvironmentLoader::prepareAppEnvironment()));
+}
diff --git a/dotenv/loader.sh b/dotenv/loader.sh
new file mode 100644
index 0000000000..385050de91
--- /dev/null
+++ b/dotenv/loader.sh
@@ -0,0 +1,21 @@
+## A bash file that can be sourced for loading the environment.
+#
+# Optional:
+# SITE=example - Use the respective site instead of the default site while
+# preparing the app environment.
+
+# Determine current dir and load .env file so PHAPP_ENV can be initialized.
+DIR=$( dirname "${BASH_SOURCE[0]}" )
+
+# Eport all the variables by enabling -a.
+set -a
+eval "$(php $DIR/loader.php getDotenvFiles)"
+eval "$(php $DIR/loader.php determineEnvironment)"
+
+if [ -z "$PHAPP_ENV" ]; then
+ echo "Missing .env file or PHAPP_ENV environment variable. Did you run phapp setup?"
+ return 1
+fi
+eval "$(php $DIR/loader.php prepareDeterminedEnvironment)"
+eval "$(php $DIR/loader.php prepareAppEnvironment)"
+set +a
diff --git a/dotenv/print.sh b/dotenv/print.sh
new file mode 100755
index 0000000000..ab150eb087
--- /dev/null
+++ b/dotenv/print.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+### A bash file that outputs all dotenv variables.
+#
+# Optional:
+# SITE=example - Use the respective site instead of the default site while
+# preparing the app environment.
+
+# Determine current dir and load .env file so PHAPP_ENV can be initialized.
+DIR=$( dirname $0)
+
+## Source the loader first, so PHAPP_ENV is set and can be applied by steps after determineEnvironment().
+
+source $DIR/loader.sh
+
+php $DIR/loader.php getDotenvFiles
+php $DIR/loader.php determineEnvironment
+php $DIR/loader.php prepareDeterminedEnvironment
+php $DIR/loader.php prepareAppEnvironment
diff --git a/dotenv/sites/all.env b/dotenv/sites/all.env
new file mode 100644
index 0000000000..ad4321faff
--- /dev/null
+++ b/dotenv/sites/all.env
@@ -0,0 +1,5 @@
+# Prepares .env for the given $SITE based upon the variables set by the request matcher.
+
+# Provide base URLs for all site variants.
+PHAPP_BASE_URL=$URL_SCHEME://${SITE_MAIN_HOST}
+# SITE_ADMIN_BASE_URL=$URL_SCHEME://admin${APP_SITE_VARIANT_SEPARATOR}${SITE_MAIN_HOST}
diff --git a/dotenv/sites/all.env-localdev.env b/dotenv/sites/all.env-localdev.env
new file mode 100644
index 0000000000..e8e267bca2
--- /dev/null
+++ b/dotenv/sites/all.env-localdev.env
@@ -0,0 +1,2 @@
+# Allow accessing the service from other development hosts, like webpack development server.
+DRUPAL_SERVICE_cors__config___enabled=1
diff --git a/dotenv/test.env b/dotenv/test.env
new file mode 100644
index 0000000000..2bf96376c6
--- /dev/null
+++ b/dotenv/test.env
@@ -0,0 +1,3 @@
+PHAPP_ENV_TYPE=example
+PHAPP_ENV_MODE=production
+PHAPP_ENV_COLOR=008000
diff --git a/dotenv/travis.env b/dotenv/travis.env
new file mode 100644
index 0000000000..e8cd66596b
--- /dev/null
+++ b/dotenv/travis.env
@@ -0,0 +1,16 @@
+PHAPP_ENV_TYPE=travis
+PHAPP_ENV_COLOR=69c8ff
+# Set to development so that phapp build includes dev dependencies.
+# @see phapp.yml commands.build
+PHAPP_ENV_MODE=development
+
+# Adjust available URLs while testing.
+# @see web/sites/sites.php
+URL_SCHEME=http
+APP_MULTISITE_DOMAIN={{ project }}.local
+APP_MULTISITE_DOMAIN_PREFIX_SEPARATOR="."
+
+# Make other containers join the docker-compose network.
+DOCKER_NETWORK={{ project }}_default
+BEHAT_CHROME_HOST=chrome
+ENV_UNIX_GROUP_WEBSERVER="www-data"
diff --git a/dotenv/vagrant.env b/dotenv/vagrant.env
new file mode 100644
index 0000000000..79695f89b4
--- /dev/null
+++ b/dotenv/vagrant.env
@@ -0,0 +1,9 @@
+PHAPP_ENV_TYPE=vagrant
+PHAPP_ENV_MODE=development
+PHAPP_ENV_COLOR=0066ff
+
+# Adjust available URLs while testing.
+# @see web/sites/sites.php
+URL_SCHEME=http
+APP_MULTISITE_DOMAIN={{ project }}.local
+APP_MULTISITE_DOMAIN_PREFIX_SEPARATOR="."
diff --git a/drush.wrapper b/drush.wrapper
new file mode 100755
index 0000000000..032c0ce897
--- /dev/null
+++ b/drush.wrapper
@@ -0,0 +1,32 @@
+#!/usr/bin/env sh
+#
+# DRUSH WRAPPER
+#
+# A wrapper script which launches the Drush that is in your project's /vendor
+# directory. Copy it to the root of your project and edit as desired.
+# You may rename this script to 'drush', if doing so does not cause a conflict
+# (e.g. with a folder __ROOT__/drush).
+#
+# Below are options which you might want to add. More info at
+# `drush topic core-global-options`:
+#
+# --local Only discover commandfiles/site aliases/config that are
+# inside your project dir.
+# --alias-path A list of directories where Drush will search for site
+# alias files.
+# --config A list of paths to config files
+# --include A list of directories to search for commandfiles.
+#
+# Note that it is recommended to use --local when using a drush
+# wrapper script.
+#
+# See the 'drush' script in the Drush installation root (../drush) for
+# an explanation of the different 'drush' scripts.
+#
+# IMPORTANT: Modify the path below if your 'vendor' directory has been
+# relocated to another location in your composer.json file.
+# `../vendor/bin/drush.launcher --local $@` is a common variant for
+# composer-managed Drupal sites.
+#
+cd "`dirname $0`/web"
+../vendor/bin/drush --local "$@"
diff --git a/drush/ci.alias.yml b/drush/ci.alias.yml
new file mode 100644
index 0000000000..df863359d1
--- /dev/null
+++ b/drush/ci.alias.yml
@@ -0,0 +1,16 @@
+develop:
+ uri: '{{ project }}.ci.drunomics.com'
+ root: /srv/default/web
+ remote-host: '{{ project }}.ci.drunomics.com'
+ target-command-specific:
+ sql-sync:
+ enable:
+ - stage_file_proxy
+master:
+ uri: '{{ project }}--master.ci.drunomics.com'
+ root: /srv/default/web
+ remote-host: '{{ project }}--master.ci.drunomics.com'
+ target-command-specific:
+ sql-sync:
+ enable:
+ - stage_file_proxy
diff --git a/drush/drush.yml b/drush/drush.yml
new file mode 100644
index 0000000000..94ecf9183f
--- /dev/null
+++ b/drush/drush.yml
@@ -0,0 +1,50 @@
+# Drush config.
+---
+sql:
+ # List of tables whose *data* is skipped by the 'sql-dump' and 'sql-sync'
+ # commands when the "--structure-tables-key=common" option is provided.
+ # You may add specific tables to the existing array or add a new element.
+ structure-tables:
+ common:
+ - cache
+ - 'cache_*'
+ - history
+ - 'search_index'
+ - 'search_total'
+ - 'sessions'
+ - 'watchdog'
+ # List of tables to be omitted entirely from SQL dumps made by the 'sql-dump'
+ # and 'sql-sync' commands when the "--skip-tables-key=common" option is
+ # provided on the command line. This is useful if your database contains
+ # non-Drupal tables used by some other application or during a migration for
+ # example. You may add new tables to the existing array or add a new element.
+ skip-tables:
+ common:
+ - 'migration_*'
+
+command:
+ sql:
+ dump:
+ options:
+ # Use common tables by default.
+ structure-tables-key: common
+ skip-tables-key: common
+ # Dump to standard dump location by default.
+ result-file: ../dumps/sync/dump.sql
+ gzip: true
+ sql-sync:
+ options:
+ create-db: true
+ # Use common tables by default.
+ structure-tables-key: common
+ skip-tables-key: common
+ site:
+ install:
+ options:
+ locale: '${env.DEFAULT_LANGUAGE}'
+ # Set a predetermined username and password when using site-install.
+ account-name: dru_admin
+ account-pass: '${env.APP_SECRET}'
+
+options:
+ uri: '${env.PHAPP_BASE_URL}'
diff --git a/drush/policy.drush.inc b/drush/policy.drush.inc
deleted file mode 100644
index 64cd62d0f6..0000000000
--- a/drush/policy.drush.inc
+++ /dev/null
@@ -1,38 +0,0 @@
-\" - re-run phapp setup to update.\n####\n" > .env
+ cat .env-defaults >> .env
+ # Support per environment .env additions and local overrides.
+ [[ ! -f .env-$PHAPP_ENV.dist ]] || (cat .env-$PHAPP_ENV.dist >> .env)
+ [[ ! -f .env.local ]] || (cat .env.local >> .env)
+ echo "PHAPP_ENV=$PHAPP_ENV" > .current.env
+ ./scripts/setup-base.sh
+ ./scripts/generate-network-aliases.sh
+ environment: |
+ source dotenv/loader.sh
+ build: |
+ EXTRA_ARGS=$([[ $PHAPP_ENV_MODE = 'production' ]] && echo '--no-dev' || echo '');
+ composer install --no-interaction $EXTRA_ARGS
+ clean: |
+ # Clean composer vendor via the provided script.
+ composer clean
+ status: |
+ drush status --fields=bootstrap | grep 'bootstrap' -q
+ init: |
+ drush sql-create -y &&
+ zcat dumps/init.sql.gz | drush sql:cli &&
+ drush updatedb -y &&
+ # Skip config-import when there is no config.
+ if [ -f config/sync/core.extension.yml ]; then
+ drush phapp:apply-env-mode && drush cim -y && drush cr
+ fi &&
+ drush locale:check && drush locale:update
+ install: |
+ chmod +w web/sites/default &&
+ drush sql-create -y &&
+ SITE=${SITE:-default} &&
+ drush site-install -y --sites-subdir=$SITE --config-dir=../config/sync ${INSTALL_PROFILE:-minimal} &&
+ drush en admin_toolbar_tools dsk_config_split services_env_parameter -y
+ update: |
+ drush updatedb -y &&
+ # Skip config-import when there is no config.
+ if [ -f config/sync/core.extension.yml ]; then
+ drush phapp:apply-env-mode && drush cim -y && drush cr
+ fi &&
+ drush locale:check && drush locale:update
diff --git a/phpcs.xml.dist b/phpcs.xml.dist
new file mode 100644
index 0000000000..72f536ea29
--- /dev/null
+++ b/phpcs.xml.dist
@@ -0,0 +1,64 @@
+
+
+
+
+ Default drunomics Coding Style for Drupal 8.
+
+ ./tests/behat/behat-features/src
+ ./scripts
+ ./web/modules/custom
+
+ ./scripts/composer/ScriptHandler.php
+ *md
+ ./scripts/composer/ScriptHandler.php
+ ./scripts
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ */src/Annotation
+
+
+
+ ./scripts
+ */tests
+
+
+
+
+ ./scripts
+
+
+
+
+ ./tests/behat/behat-features
+
+
+
+
+
+
+
+ ./drush
+
+
+ ./drush
+
+
+ ./drush
+
+
+
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index ce29746d7c..19c8f4491a 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,15 +1,80 @@
-
-
-
- ./test/
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ./web/core/tests/TestSuites/UnitTestSuite.php
+
+
+ ./web/core/tests/TestSuites/KernelTestSuite.php
+
+
+ ./web/core/tests/TestSuites/FunctionalTestSuite.php
+
+
+ ./web/core/tests/TestSuites/FunctionalJavascriptTestSuite.php
+
+
+ ./web/core//tests/TestSuites/BuildTestSuite.php
+
+
+
+
+
+
+
+
+
+
+
+
+ ./web/core/includes
+ ./web/core/lib
+
+ ./web/core/modules
+
+ ./web/core/modules/*/src/Tests
+ ./web/core/modules/*/tests
+
+ ./web/modules
+
+ ./web/modules/*/src/Tests
+ ./web/modules/*/tests
+ ./web/modules/*/*/src/Tests
+ ./web/modules/*/*/tests
+
+ ./web/sites
+
+
diff --git a/scripts/composer/CleanCommand.php b/scripts/composer/CleanCommand.php
new file mode 100644
index 0000000000..2823be0bfb
--- /dev/null
+++ b/scripts/composer/CleanCommand.php
@@ -0,0 +1,37 @@
+getComposer();
+ $io = $event->getIO();
+
+ $repo = $composer->getRepositoryManager()
+ ->getLocalRepository();
+ /** @var \Composer\Repository\RepositoryInterface $repo */
+
+ $filesystem = new Filesystem();
+ foreach ($repo->getPackages() as $package) {
+ $path = $composer->getInstallationManager()->getInstallPath($package);
+ if (is_dir($path) && !$filesystem->isDirEmpty($path)) {
+ $io->write("Cleaning package " . $package->getPrettyName() . '>');
+ $filesystem->remove($path);
+ }
+ }
+
+ }
+
+}
diff --git a/scripts/composer/PharInstaller.php b/scripts/composer/PharInstaller.php
new file mode 100644
index 0000000000..830ac536d4
--- /dev/null
+++ b/scripts/composer/PharInstaller.php
@@ -0,0 +1,63 @@
+getComposer();
+ $bin_dir = $composer->getConfig()->get('bin-dir');
+ $extras = $composer->getPackage()->getExtra();
+
+ if (array_key_exists('tools', $extras)) {
+ foreach ($extras['tools'] as $tool => $data) {
+ if (empty($data['url'])) {
+ throw new \LogicException("Missing tool url.");
+ }
+ if (!empty($data['dev']) && !$event->isDevMode()) {
+ continue;
+ }
+ $filename = basename($data['url']) . '-' . $data['version'];
+
+ if (!$fs->exists("$bin_dir/$filename")) {
+ if (!$fs->exists($bin_dir)) {
+ $fs->mkdir($bin_dir);
+ }
+ $event->getIO()->write("Downloading $filename...");
+ $content = static::download($data['url']);
+ $fs->dumpFile("$bin_dir/$filename", $content);
+ $fs->chmod("$bin_dir/$filename", 0755);
+
+ if ($fs->exists("$bin_dir/$tool")) {
+ $fs->remove("$bin_dir/$tool");
+ }
+ $fs->symlink($filename, "$bin_dir/$tool");
+ }
+ }
+ }
+ }
+
+ /**
+ * Downloads the URL.
+ */
+ protected static function download($url) {
+ $context = StreamContextFactory::getContext($url);
+ return file_get_contents($url, FALSE, $context);
+ }
+
+}
diff --git a/scripts/composer/ScriptHandler.php b/scripts/composer/ScriptHandler.php
index a75e4d34ee..59b217d1d5 100644
--- a/scripts/composer/ScriptHandler.php
+++ b/scripts/composer/ScriptHandler.php
@@ -35,22 +35,6 @@ public static function createRequiredFiles(Event $event) {
}
}
- // Prepare the settings file for installation
- if (!$fs->exists($drupalRoot . '/sites/default/settings.php') and $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';
- $settings['config_directories'] = [
- 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("Create a sites/default/settings.php file with chmod 0666");
- }
-
// Create the files directory with chmod 0777
if (!$fs->exists($drupalRoot . '/sites/default/files')) {
$oldmask = umask(0);
diff --git a/scripts/composer/process-replacements.php b/scripts/composer/process-replacements.php
new file mode 100755
index 0000000000..519a6bb12d
--- /dev/null
+++ b/scripts/composer/process-replacements.php
@@ -0,0 +1,62 @@
+#!/usr/bin/php
+ $project,
+ // Provide a version with underscore delimiters.
+ "{{ project_underscore }}" => str_replace('-', '_', $project),
+ "{{ hash_salt }}" => random_string(32),
+ "{{ secret_long }}" => random_string(32),
+ "{{ secret }}" => random_string(12),
+];
+
+// Process replacements.
+foreach ($file_patterns as $pattern) {
+
+ foreach (glob($pattern, GLOB_BRACE) as $file) {
+ $content = file_get_contents($file);
+ if (($new_content = strtr($content, $replacements)) != $content) {
+ echo "Processing replacements in file $file...\n";
+ file_put_contents($file, $new_content);
+ }
+ }
+}
+
+exit(0);
diff --git a/scripts/generate-network-aliases.sh b/scripts/generate-network-aliases.sh
new file mode 100755
index 0000000000..ba7eaaf2e9
--- /dev/null
+++ b/scripts/generate-network-aliases.sh
@@ -0,0 +1,41 @@
+#!/bin/bash -e
+
+######
+# Extends the main docker-compose file with network aliases for localdev inner-container hostname resolution.
+# This allows containers in the 'traefik' network to connect to this app under the given hostnames.
+######
+source `dirname $0`/util/os-compat-helpers.sh
+TEMPLATE_FILE=`os_compat_readlink -f $(dirname $0)`/generate-network-aliases.template.yml
+cd `dirname $0`/..
+source dotenv/loader.sh
+
+# Only generate this for the localdev environment.
+if [[ ! $PHAPP_ENV = "localdev" ]]; then
+ rm -f docker-compose.overrides.aliases.yml
+ exit 0
+fi
+
+PROJECT=$(basename $PWD)
+HOSTS=''
+for SITE in $APP_SITES; do
+ # Re-run dotenv loader to determine SITE_HOST, without variant.
+ SITE_VARIANT=''
+ source dotenv/loader.sh
+ HOSTS+="$SITE_HOST "
+ for SITE_VARIANT in $APP_SITE_VARIANTS; do
+ # Re-run dotenv loader to determine SITE_HOST.
+ source dotenv/loader.sh
+ HOSTS+="$SITE_HOST "
+ done
+done
+
+## Generate the new file.
+cat $TEMPLATE_FILE > docker-compose.overrides.aliases.yml
+
+for HOST in $HOSTS; do
+ echo " - $HOST" >> docker-compose.overrides.aliases.yml
+done
+
+## Register the compose file.
+os_compat_sed_i '/^COMPOSE_FILE/ s/ *$/:docker-compose.overrides.aliases.yml/' .env
+echo "docker-compose.overrides.aliases.yml generated."
diff --git a/scripts/generate-network-aliases.template.yml b/scripts/generate-network-aliases.template.yml
new file mode 100644
index 0000000000..9f2d2ddfd2
--- /dev/null
+++ b/scripts/generate-network-aliases.template.yml
@@ -0,0 +1,12 @@
+# Extends the main docker-compose file with network aliases for localdev inner-container hostname resolution.
+# This allows containers in the 'traefik' network to connect to this app under the given hostnames.
+#
+## NOTE: Do not modify. This file is generated via scripts/util/generate-network-aliases.sh.
+#
+version: '2.3'
+services:
+ varnish:
+ networks:
+ traefik:
+ aliases:
+ - ${COMPOSE_HOSTNAME}
diff --git a/scripts/init-devsetup-docker.sh b/scripts/init-devsetup-docker.sh
new file mode 100755
index 0000000000..0242d84d55
--- /dev/null
+++ b/scripts/init-devsetup-docker.sh
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+
+cd `dirname $0`/..
+set -ex
+
+PROJECT_ADD_DEVSETUP_DOCKER=${PROJECT_ADD_DEVSETUP_DOCKER:-1}
+
+if [[ $PROJECT_ADD_DEVSETUP_DOCKER = 1 ]]; then
+ echo "Adding devsetup-docker from https://github.com/drunomics/devsetup-docker..."
+ echo "Set PROJECT_ADD_DEVSETUP_DOCKER=0 to disable."
+
+ git clone https://github.com/drunomics/devsetup-docker.git --branch=3.x devsetup-tmp
+ rm -rf devsetup-tmp/.git devsetup-tmp/README.md
+
+ # OS specific cp operations
+ case "$OSTYPE" in
+ darwin*)
+ if [ -d "./devsetup-tmp" ]
+ then
+ cp -rf devsetup-tmp/* .
+ cp -rf devsetup-tmp/.[^.]* .
+ fi ;;
+ linux*) cp -rfT devsetup-tmp . ;;
+ *) cp -rfT devsetup-tmp . ;;
+ esac
+
+ # Apply replacements and cleanup.
+ php process-replacements.php
+ rm -rf devsetup-tmp process-replacements.php
+ echo \
+'COMPOSE_AMAZEEIO_VERSION=v1.9.1
+COMPOSE_AMAZEEIO_PHP_VERSION=7.4
+' >> .env-defaults
+fi
diff --git a/scripts/init-devsetup-drunomics.sh b/scripts/init-devsetup-drunomics.sh
new file mode 100755
index 0000000000..dbbad21af9
--- /dev/null
+++ b/scripts/init-devsetup-drunomics.sh
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+
+cd `dirname $0`/..
+set -e
+
+# Only do something if explicitly enabled.
+if [[ -z $PROJECT_ADD_DEVSETUP_DRUNOMICS ]]; then
+ echo "Variable PROJECT_ADD_DEVSETUP_DRUNOMICS is not set, skipping..."
+ exit 0
+fi
+
+mkdir devsetup-tmp
+git clone git@bitbucket.org:drunomics/project-devsetup.git devsetup-tmp
+rm -rf devsetup-tmp/.git
+rm devsetup-tmp/README.md
+cp -rf devsetup-tmp/* .
+rm -rf devsetup-tmp
diff --git a/scripts/run-cron.sh b/scripts/run-cron.sh
new file mode 100755
index 0000000000..5bedb947fe
--- /dev/null
+++ b/scripts/run-cron.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+cd `dirname $0`/..
+
+DIR=`pwd`
+DRUSH_BIN=$DIR/vendor/bin/drush
+DRUSH_PHP=$PHP_BIN $DRUSH_BIN cron --quiet
diff --git a/scripts/setup-base.sh b/scripts/setup-base.sh
new file mode 100755
index 0000000000..ce45bf7c45
--- /dev/null
+++ b/scripts/setup-base.sh
@@ -0,0 +1,62 @@
+#!/usr/bin/env bash
+#
+# Base setup script. Takes care of setting up files directories.
+#
+# This will be invoked via the phapp setup command when a site is setup.
+cd `dirname $0`/..
+source scripts/util/os-compat-helpers.sh
+
+# Copy example settings.
+cp web/sites/example.local.services.yml web/sites/local.services.yml
+cp web/sites/example.local.settings.php web/sites/local.settings.php
+
+# For drunomics-CI generate additional variables that can be used in its
+# dotenv file.
+if [[ $PHAPP_ENV = "drunomics-ci" ]]; then
+ echo "CONTAINER_HOST=$(hostname -f)" > .container.env
+ echo "CONTAINER_NAME=$(hostname -s)" >> .container.env
+fi
+
+# Default to first sub-site during development.
+if [ ! -L web/sites/default ]; then
+ rm -rf web/sites/default
+ DIR=$(cd web/sites/ && ls -d */ | grep -v all/ | head -n 1)
+ ln -s $DIR web/sites/default
+fi
+
+# Load dotenv.
+source dotenv/loader.sh
+
+# Be sure files directories are setup.
+for SITE in `ls -d web/sites/*/`; do
+ SITE=`basename $SITE`
+
+ if [[ $SITE == 'all' ]] || [[ $SITE == 'default' ]]; then
+ continue;
+ fi
+
+ mkdir -p $PERSISTENT_FILES_DIR/$SITE/public/translations
+ mkdir -p $PERSISTENT_FILES_DIR/$SITE/private
+
+ if [ -n "$ENV_UNIX_GROUP_WEBSERVER" ]; then
+ sudo chown -R :$ENV_UNIX_GROUP_WEBSERVER $PERSISTENT_FILES_DIR/$SITE/
+ # When a custom group is set, ensure sub-directory and files are always
+ # webserver writable via the setgid bit. This makes the right group to be
+ # propagated down.
+ sudo chmod 2775 $PERSISTENT_FILES_DIR/$SITE/public
+ sudo chmod 2775 $PERSISTENT_FILES_DIR/$SITE/public/translations
+ sudo chmod 2775 $PERSISTENT_FILES_DIR/$SITE/private
+ fi
+
+ # Move files for existing dev-installations.
+ if [[ -d web/sites/$SITE/files ]] && [[ ! -L web/sites/$SITE/files ]]; then
+ # Ignore errors moving something.
+ mv web/sites/$SITE/files/* $PERSISTENT_FILES_DIR/$SITE/public || true
+ rm -rf web/sites/$SITE/files
+ fi
+
+ # Link public files directory to persistent files.
+ mkdir -p web/sites/$SITE
+ os_compat_link_directory ../../../$PERSISTENT_FILES_DIR/$SITE/public web/sites/$SITE/files
+done
+
diff --git a/scripts/update-init-dump.sh b/scripts/update-init-dump.sh
new file mode 100755
index 0000000000..4b75b22c8d
--- /dev/null
+++ b/scripts/update-init-dump.sh
@@ -0,0 +1,45 @@
+#!/usr/bin/env bash
+
+# Script updates the init dump for the project.
+
+# Optionally, this can be done in two steps:
+# ./scripts/update-init-dump.sh --abort-before-dump
+# adjust the dump then finish:
+# ./scripts/update-init-dump.sh --skip-preparation
+
+set -e
+cd $(dirname $0)/..
+source dotenv/loader.sh
+
+# Call with `VERBOSE=1 SCRIPT to see commands printed.
+if [[ $VERBOSE = "1" ]]; then
+ set -x
+fi
+
+# A file used to temporarily force production mode.
+ENV_FILE=dotenv/$PHAPP_ENV.env
+
+if [[ ! $1 = '--skip-preparation' ]]; then
+ echo "Forcing environment to production mode..."
+ sed -i 's/PHAPP_ENV_MODE=.*$/PHAPP_ENV_MODE=production/g' $ENV_FILE
+
+ echo "Initializing app in production mode..."
+ git checkout origin/develop -- dumps/init.sql.gz
+ ([ ! -f web/sites/default/phapp.yml ] || cd web/sites/default && phapp init)
+else
+ echo "WARNING: Skipping preparation, dumping current database!"
+fi
+
+if [[ $1 = '--abort-before-dump' ]]; then
+ echo "Aborting before dumping, site is forced into production mode."
+ exit
+fi
+
+echo "Creating new init dump..."
+drush sql-dump --result-file=../dumps/init.sql --gzip
+
+echo "Stopping to force the site into production mode..."
+git checkout origin/develop -- $ENV_FILE
+
+echo "Done."
+echo "Note: Run 'phapp update' to apply current config again."
diff --git a/scripts/util/exec.sh b/scripts/util/exec.sh
new file mode 100755
index 0000000000..68c53e41f0
--- /dev/null
+++ b/scripts/util/exec.sh
@@ -0,0 +1,68 @@
+#!/usr/bin/env bash
+
+# Runs any command as needed in the current environment; i.e. either directly or
+# by passing it off to a docker container.
+
+# The script output the command run (via set -x) if the command is passed of.
+# If the command is directly executed there is no extra output.
+
+# Set "VERBOSE" to 1 to enable verbose output.
+
+cd `dirname $0`/../..
+set +x
+source ./dotenv/loader.sh
+set -e
+
+COMMANDS=${@}
+
+if [[ ! $COMMANDS ]]; then
+ echo "USAGE:"
+ echo -n "$0 "
+ echo 'echo Example pwd: \&\& pwd'
+ echo
+
+ echo "Via heredoc so no escaping is necessary:"
+ echo "$0 - <