├── .env.example
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build.dist.xml
├── build.properties.dist
├── build.xml
├── composer.json
├── drush
├── Commands
│ └── PolicyCommands.php
├── README.md
├── drush.yml.dist
└── sites
│ └── self.site.yml
├── load.environment.php
├── phpcs-ruleset.xml.dist
├── phpunit.xml.dist
├── scripts
├── composer
│ └── ScriptHandler.php
└── travis-ci
│ └── run-test.sh
├── src
└── Phing
│ ├── PhpCodeSnifferConfigurationTask.php
│ └── PhpUnitConfigurationTask.php
└── tests
├── behat
├── behat.yml.dist
└── features
├── authentication.feature
└── bootstrap
└── FeatureContext.php
/.env.example:
--------------------------------------------------------------------------------
1 | #
2 | # Copy and rename this file to .env at root of this project.
3 | #
4 |
5 | # A common use case is to supply database creds via the environment. Edit settings.php
6 | # like so:
7 | #
8 | # $databases['default']['default'] = [
9 | # 'database' => getenv('MYSQL_DATABASE'),
10 | # 'driver' => 'mysql',
11 | # 'host' => getenv('MYSQL_HOSTNAME'),
12 | # 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
13 | # 'password' => getenv('MYSQL_PASSWORD'),
14 | # 'port' => getenv('MYSQL_PORT'),
15 | # 'prefix' => '',
16 | # 'username' => getenv('MYSQL_USER'),
17 | # ];
18 | #
19 | # Uncomment and populate as needed.
20 | # MYSQL_DATABASE=
21 | # MYSQL_HOSTNAME=
22 | # MYSQL_PASSWORD=
23 | # MYSQL_PORT=
24 | # MYSQL_USER=
25 |
26 | # Another common use case is to set Drush's --uri via environment.
27 | # DRUSH_OPTIONS_URI=http://example.com
28 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore directories generated by Composer
2 | /bin/
3 | /drush/contrib/
4 | /vendor/
5 | /web/core/
6 | /web/libraries/
7 | /web/modules/contrib/
8 | /web/profiles/contrib/
9 | /web/themes/contrib/
10 |
11 | # Ignore sensitive information
12 | /web/sites/*/settings.php
13 | /web/sites/*/settings.local.php
14 |
15 | # Ignore Drupal's file directory
16 | /web/sites/*/files/
17 |
18 | # Ignore SimpleTest multi-site environment.
19 | /web/sites/simpletest/
20 |
21 | # Ignore environment specific settings
22 | /build.local.xml
23 | /build.properties.local
24 | /drush/drush.yml
25 | /phpcs.xml
26 | /tests/behat.yml
27 | /web/phpunit.xml
28 | /web/sites/default/services.yml
29 |
30 | # Ignore files generated by PhpStorm
31 | /.idea/
32 |
33 | # Ignore .env files as they are personal
34 | /.env
35 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 7.0
5 | - 7.1
6 | - 7.2
7 | - 7.3
8 |
9 | sudo: false
10 |
11 | mysql:
12 | database: myproject
13 | username: root
14 | encoding: utf8
15 |
16 | env:
17 | - TEST=PHP_CodeSniffer
18 | - TEST=PHPUnit
19 | - TEST=Behat
20 |
21 | matrix:
22 | exclude:
23 | - php: 7.0
24 | env: TEST=PHP_CodeSniffer
25 | - php: 7.1
26 | env: TEST=PHP_CodeSniffer
27 | - php: 7.3
28 | env: TEST=PHP_CodeSniffer
29 |
30 | matrix:
31 | allow_failures:
32 | - php: 7.3
33 |
34 | before_install:
35 | # Remove Xdebug as we don't need it and it causes "PHP Fatal error: Maximum
36 | # function nesting level of '256' reached". We don't care if that file exists
37 | # or not on PHP 7.
38 | - phpenv config-rm xdebug.ini || true
39 |
40 | # Update composer.
41 | - composer --verbose self-update
42 |
43 | # Create database.
44 | - mysql -e 'create database myproject'
45 |
46 | install:
47 | # Install Composer dependencies.
48 | - composer --verbose install
49 |
50 | # Define build properties for the local test environment.
51 | - echo -e "drupal.base_url = http://localhost:8888\n" > build.properties.local
52 |
53 | # Build the project.
54 | - ./vendor/bin/phing build-dev
55 |
56 | # Install Drupal. This is not needed when doing a coding standards check.
57 | - test ${TEST} == "PHP_CodeSniffer" || ./vendor/bin/phing install-dev
58 |
59 | # Start a web server on port 8888 in the background.
60 | - cd $TRAVIS_BUILD_DIR/web
61 | - nohup php -S localhost:8888 > /dev/null 2>&1 &
62 |
63 | # Wait until the web server is responding.
64 | - until curl -s localhost:8888; do true; done > /dev/null
65 | - cd $TRAVIS_BUILD_DIR
66 |
67 | script: ./scripts/travis-ci/run-test.sh ${TEST}
68 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Composer template for Drupal projects
2 |
3 | [](https://travis-ci.org/drupal-composer/drupal-project)
4 |
5 | This project template provides a starter kit for managing your site
6 | dependencies with [Composer](https://getcomposer.org/).
7 |
8 | This is a fork of [drupal-composer/drupal-project](https://github.com/drupal-composer/drupal-project)
9 | which is set up with support for Continuous Integration out of the box.
10 |
11 | ## Additional features
12 |
13 | This fork has the following additions to the original version of drupal-project:
14 |
15 | * **Customizable builds**: Different builds for production and development
16 | environments are created with [Phing](https://www.phing.info/). These can be
17 | fully customized using a set of configuration files.
18 | * **Behat support**: Behat is included so you can easily test user scenarios.
19 | * **Preconfigured test suites**: PHPUnit is fully set up for running unit tests
20 | as well as kernel tests, web tests and javascript tests.
21 | * **PHP CodeSniffer**: Check compliance with coding standards with a single
22 | command, or set it up to scan automatically whenever you `git push`.
23 | * **Travis CI**: Integrates seamlessly with [Travis CI](https://travis-ci.com/)
24 | so you can automate your tests right from the start. No setup needed!
25 |
26 | If you want to know how to use it as replacement for
27 | [Drush Make](https://github.com/drush-ops/drush/blob/8.x/docs/make.md) visit
28 | the [Documentation on drupal.org](https://www.drupal.org/node/2471553).
29 |
30 | ## Usage
31 |
32 | First you need to [install composer](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx).
33 |
34 | > Note: The instructions below refer to the [global composer installation](https://getcomposer.org/doc/00-intro.md#globally).
35 | You might need to replace `composer` with `php composer.phar` (or similar)
36 | for your setup.
37 |
38 | After that you can create the project:
39 |
40 | ```
41 | git clone https://github.com/pfrenssen/drupal-project.git some-dir
42 | cd some-dir
43 | composer install
44 | ```
45 |
46 | With `composer require ...` you can download new dependencies to your
47 | installation.
48 |
49 | ```
50 | composer require drupal/devel:~1.0
51 | ```
52 |
53 | The `composer create-project` command passes ownership of all files to the
54 | project that is created. You should create a new git repository, and commit
55 | all files not excluded by the .gitignore file.
56 |
57 | ## What does the template do?
58 |
59 | When installing the given `composer.json` some tasks are taken care of:
60 |
61 | * Drupal will be installed in the `web`-directory.
62 | * Autoloader is implemented to use the generated composer autoloader in `vendor/autoload.php`,
63 | instead of the one provided by Drupal (`web/vendor/autoload.php`).
64 | * Modules (packages of type `drupal-module`) will be placed in `web/modules/contrib/`
65 | * Theme (packages of type `drupal-theme`) will be placed in `web/themes/contrib/`
66 | * Profiles (packages of type `drupal-profile`) will be placed in `web/profiles/contrib/`
67 | * Creates default writable versions of `settings.php` and `services.yml`.
68 | * Creates `web/sites/default/files`-directory.
69 | * Latest version of drush is installed locally for use at `vendor/bin/drush`.
70 | * Latest version of DrupalConsole is installed locally for use at `vendor/bin/drupal`.
71 | * Creates environment variables based on your .env file. See [.env.example](.env.example).
72 |
73 | ## Updating Drupal Core
74 |
75 | This project will attempt to keep all of your Drupal Core files up-to-date; the
76 | project [drupal-composer/drupal-scaffold](https://github.com/drupal-composer/drupal-scaffold)
77 | is used to ensure that your scaffold files are updated every time drupal/core is
78 | updated. If you customize any of the "scaffolding" files (commonly .htaccess),
79 | you may need to merge conflicts if any of your modified files are updated in a
80 | new release of Drupal core.
81 |
82 | Follow the steps below to update your core files.
83 |
84 | 1. Run `composer update drupal/core webflo/drupal-core-require-dev "symfony/*" --with-dependencies` to update Drupal Core and its dependencies.
85 | 1. Run `git diff` to determine if any of the scaffolding files have changed.
86 | Review the files for any changes and restore any customizations to
87 | `.htaccess` or `robots.txt`.
88 | 1. Commit everything all together in a single commit, so `web` will remain in
89 | sync with the `core` when checking out branches or running `git bisect`.
90 | 1. In the event that there are non-trivial conflicts in step 2, you may wish
91 | to perform these steps on a branch, and use `git merge` to combine the
92 | updated core files with your customized files. This facilitates the use
93 | 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;
94 | keeping all of your modifications at the beginning or end of the file is a
95 | good strategy to keep merges easy.
96 |
97 | ## Generate composer.json from existing project
98 |
99 | With using [the "Composer Generate" drush extension](https://www.drupal.org/project/composer_generate)
100 | you can now generate a basic `composer.json` file from an existing project. Note
101 | that the generated `composer.json` might differ from this project's file.
102 |
103 |
104 | ## Customize build properties
105 |
106 | Create a new file in the root of the project named `build.properties.local`
107 | using your favourite text editor:
108 |
109 | ```
110 | $ vim build.properties.local
111 | ```
112 |
113 | This file will contain configuration which is unique to your development
114 | machine. This is mainly useful for specifying your database credentials and the
115 | username and password of the Drupal admin user so they can be used during the
116 | installation.
117 |
118 | Because these settings are personal they should not be shared with the rest of
119 | the team. Make sure you never commit this file!
120 |
121 | All options you can use can be found in the `build.properties.dist` file. Just
122 | copy the lines you want to override and change their values. For example:
123 |
124 | ```
125 | # Database settings.
126 | drupal.db.name = my_database
127 | drupal.db.user = root
128 | drupal.db.password = hunter2
129 |
130 | # Admin user.
131 | drupal.admin.username = admin
132 | drupal.admin.password = admin
133 |
134 | # The base URL to use in tests.
135 | drupal.base_url = http://myproject.local
136 |
137 | # Verbosity of Drush commands. Set to 'yes' for verbose output.
138 | drush.verbose = yes
139 | ```
140 |
141 |
142 | ## Listing the available build commands
143 |
144 | You can get a list of all the available Phing build commands ("targets") with a
145 | short description of each target with the following command:
146 |
147 | ```
148 | $ ./vendor/bin/phing
149 | ```
150 |
151 |
152 | ## Install the website.
153 |
154 | ```
155 | $ ./vendor/bin/phing install
156 | ```
157 |
158 |
159 | ## Set up tools for the development environment
160 |
161 | If you want to install a version suitable for development you can execute the
162 | `setup-dev` Phing target.
163 |
164 | ```
165 | $ ./vendor/bin/phing setup-dev
166 | ```
167 |
168 | This will perform the following tasks:
169 |
170 | 1. Configure Behat.
171 | 2. Configure PHP CodeSniffer.
172 | 3. Enable 'development mode'. This will:
173 | * Enable the services in `development.services.yml`.
174 | * Show all error messages with backtrace information.
175 | * Disable CSS and JS aggregation.
176 | * Disable the render cache.
177 | * Allow test modules and themes to be installed.
178 | * Enable access to `rebuild.php`.
179 | 4. Enable development modules.
180 | 5. Create a demo user for each user role.
181 |
182 | To set up a development environment quickly, you can perform both the `install`
183 | and `setup-dev` targets at once by executing `install-dev`:
184 |
185 | ```
186 | $ ./vendor/bin/phing install-dev
187 | ```
188 |
189 |
190 | ## Running Behat tests
191 |
192 | The Behat test suite is located in the `tests/` folder. The easiest way to run
193 | them is by going into this folder and executing the following command:
194 |
195 | ```
196 | $ cd tests/
197 | $ ./behat
198 | ```
199 |
200 | If you want to execute a single test, just provide the path to the test as an
201 | argument. The tests are located in `tests/features/`:
202 |
203 | ```
204 | $ cd tests/
205 | $ ./behat features/authentication.feature
206 | ```
207 |
208 | If you want to run the tests from a different folder, then provide the path to
209 | `tests/behat.yml` with the `-c` option:
210 |
211 | ```
212 | # Run the tests from the root folder of the project.
213 | $ ./vendor/bin/behat -c tests/behat.yml
214 | ```
215 |
216 | ### Testing JavaScript functionality
217 |
218 | For testing functionality written in JavaScript you can use software such as
219 | Selenium and PhantomJS to run Behat tests in a real browser.
220 |
221 | To enable JavaScript testing for a Behat scenario, add the `@javascript` tag to
222 | the test, and make sure the WebDriver of your choice is running in the
223 | background.
224 |
225 | #### Chrome
226 |
227 | Set the following build property in your `build.properties` file:
228 |
229 | ```
230 | # The browser to use for testing, either 'firefox' or 'chrome'.
231 | behat.browser_name = chrome
232 | ```
233 |
234 | Make sure to regenerate your Behat configuration file after making this change:
235 |
236 | ```
237 | $ ./vendor/bin/phing setup-behat
238 | ```
239 |
240 | You can install Selenium and Chrome / Chromium locally on your system and start
241 | Selenium with `java -jar selenium-server-standalone.jar`.
242 |
243 | However the simplest way of running Chrome on Selenium is using a container.
244 | You can use Docker to install and run it with a single command. This will
245 | download all necessary files and start it in the background in headless mode:
246 |
247 | ```
248 | $ docker run -d -p 4444:4444 --network=host selenium/standalone-chrome
249 | ```
250 |
251 | If you want to look at the browser running, you can run the 'debug' version and
252 | use a VNC client such as TigerVNC to connect to the browser (the password is
253 | 'secret'):
254 |
255 | ```
256 | $ docker run -d -p 4444:4444 -p 5900:5900 --network=host selenium/standalone-chrome-debug
257 | ```
258 |
259 | For more information on running a containerized Selenium, see
260 | [SeleniumHQ/docker-selenium](https://github.com/SeleniumHQ/docker-selenium).
261 |
262 |
263 | #### Firefox
264 |
265 | Set the following build property in your `build.properties` file:
266 |
267 | ```
268 | # The browser to use for testing, either 'firefox' or 'chrome'.
269 | behat.browser_name = firefox
270 | ```
271 | Make sure to regenerate your Behat configuration file after making this change:
272 |
273 | ```
274 | $ ./vendor/bin/phing setup-behat
275 | ```
276 |
277 | You can install Selenium and Firefox locally on your system and start Selenium
278 | with `java -jar selenium-server-standalone.jar`.
279 |
280 | However the simplest way of running Firefox on Selenium is using a container.
281 | You can use Docker to install and run it with a single command. This will
282 | download all necessary files and start it in the background in headless mode:
283 |
284 |
285 | ```
286 | $ docker run -d -p 4444:4444 --network=host selenium/standalone-firefox:2.53.1
287 | ```
288 |
289 | Note that the WebDriver implementation for Firefox
290 | ([Marionette](https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette))
291 | is not yet complete for Selenium 3, so we are specifying the latest 2.x
292 | version. This will probably be ready soon, when Selenium 3 is out of beta.
293 |
294 | If you want to look at the browser running, you can run the 'debug' version and
295 | use a VNC client such as TigerVNC to connect to the browser (the password is
296 | 'secret'):
297 |
298 | ```
299 | $ docker run -d -p 4444:4444 -p 5900:5900 --network=host selenium/standalone-firefox-debug:2.53.1
300 | ```
301 |
302 | For more information on running a containerized Selenium, see
303 | [SeleniumHQ/docker-selenium](https://github.com/SeleniumHQ/docker-selenium).
304 |
305 |
306 | #### PhantomJS
307 |
308 | PhantomJS is a headless browser based on Webkit, which is the same engine which
309 | Chrome uses. You can install it from your package manager, or [download
310 | it](http://phantomjs.org/download.html).
311 |
312 | Declare that you are using a Chrome-alike browser in your `build.properties`
313 | file:
314 |
315 |
316 | ```
317 | # The browser to use for testing, either 'firefox' or 'chrome'.
318 | behat.browser_name = chrome
319 | ```
320 |
321 | Make sure to regenerate your Behat configuration file after making this change:
322 |
323 | ```
324 | $ ./vendor/bin/phing setup-behat
325 | ```
326 |
327 | Now you can run PhantomJS in WebDriver mode, and run your tests. All your tests
328 | marked with `@javascript` will now be executed using PhantomJS.
329 |
330 | ```
331 | $ phantomjs --webdriver=4444
332 | ```
333 |
334 |
335 | ## Running PHPUnit tests
336 |
337 | Run the tests from the `web` folder:
338 |
339 | ```
340 | $ cd web/
341 | $ ../vendor/bin/phpunit
342 | ```
343 |
344 | By default all tests in the folders `web/modules/custom`, `web/profiles` and
345 | `web/themes/custom` are included when running the tests. Check the section on
346 | PHPUnit in the `build.properties.dist` to customize the tests.
347 |
348 |
349 | ## Checking for coding standards violations
350 |
351 | ### Set up PHP CodeSniffer
352 |
353 | PHP CodeSniffer is included to do coding standards checks of PHP and JS files.
354 | In the default configuration it will scan all files in the following folders:
355 | - `web/modules` (excluding `web/modules/contrib`)
356 | - `web/profiles`
357 | - `web/themes`
358 |
359 | First you'll need to execute the `setup-php-codesniffer` Phing target (note that
360 | this also runs as part of the `install-dev` and `setup-dev` targets):
361 |
362 | ```
363 | $ ./vendor/bin/phing setup-php-codesniffer
364 | ```
365 |
366 | This will generate a `phpcs.xml` file containing settings specific to your local
367 | environment. Make sure to never commit this file.
368 |
369 | ### Run coding standards checks
370 |
371 | #### Run checks manually
372 |
373 | The coding standards checks can then be run as follows:
374 |
375 | ```
376 | # Scan all files for coding standards violations.
377 | $ ./vendor/bin/phpcs
378 |
379 | # Scan only a single folder.
380 | $ ./vendor/bin/phpcs web/modules/custom/mymodule
381 | ```
382 |
383 | #### Run checks automatically when pushing
384 |
385 | To save yourself the embarrassment of pushing non-compliant code to the git
386 | repository you can put the following line in your `build.properties.local`:
387 |
388 | ```
389 | # Whether or not to run a coding standards check before doing a git push. Note
390 | # that this will abort the push if the coding standards check fails.
391 | phpcs.prepush.enable = 1
392 | ```
393 |
394 | and then regenerate your PHP CodeSniffer configuration:
395 |
396 | ```
397 | $ ./vendor/bin/phing setup-php-codesniffer
398 | ```
399 |
400 | If your project requires all team members to follow coding standards, put this
401 | line in the project configuration (`build.properties`) instead.
402 |
403 | Note that this will not allow you to push any code that fails the coding
404 | standards check. If you really need to push in a hurry, then you can disable
405 | the coding standards check by executing this Phing target:
406 |
407 | ```
408 | $ ./vendor/bin/phing disable-pre-push
409 | ```
410 |
411 | The pre-push hook will be reinstated when the `setup-php-codesniffer` target
412 | is executed.
413 |
414 |
415 | ### Customize configuration
416 |
417 | The basic configuration can be changed by copying the relevant Phing properties
418 | from the "PHP CodeSniffer configuration" section in `build.properties.dist` to
419 | `build.properties` and changing them to your requirements. Then regenerate the
420 | `phpcs.xml` file by running the `setup-php-codesniffer` target:
421 |
422 | ```
423 | $ ./vendor/bin/phing setup-php-codesniffer
424 | ```
425 |
426 | To change to PHP CodeSniffer ruleset itself, make a copy of the file
427 | `phpcs-ruleset.xml.dist` and rename it to `phpcs-ruleset.xml`, and then put this
428 | line in your `build.properties` file:
429 |
430 | ```
431 | phpcs.standard = ${project.basedir}/phpcs-ruleset.xml
432 | ```
433 |
434 | For more information on configuring the ruleset see [Annotated ruleset](http://pear.php.net/manual/en/package.php.php-codesniffer.annotated-ruleset.php).
435 |
436 |
437 | ## FAQ
438 |
439 | ### Should I commit the contrib modules I download?
440 |
441 | Composer recommends **no**. They provide [argumentation against but also
442 | workrounds if a project decides to do it anyway](https://getcomposer.org/doc/faqs/should-i-commit-the-dependencies-in-my-vendor-directory.md).
443 |
444 | ### Should I commit the scaffolding files?
445 |
446 | The [drupal-scaffold](https://github.com/drupal-composer/drupal-scaffold) plugin can download the scaffold files (like
447 | index.php, update.php, …) to the web/ directory of your project. If you have not customized those files you could choose
448 | to not check them into your version control system (e.g. git). If that is the case for your project it might be
449 | convenient to automatically run the drupal-scaffold plugin after every install or update of your project. You can
450 | achieve that by registering `@composer drupal:scaffold` as post-install and post-update command in your composer.json:
451 |
452 | ```json
453 | "scripts": {
454 | "post-install-cmd": [
455 | "@composer drupal:scaffold",
456 | "..."
457 | ],
458 | "post-update-cmd": [
459 | "@composer drupal:scaffold",
460 | "..."
461 | ]
462 | },
463 | ```
464 | ### How can I apply patches to downloaded modules?
465 |
466 | If you need to apply patches (depending on the project being modified, a pull
467 | request is often a better solution), you can do so with the
468 | [composer-patches](https://github.com/cweagans/composer-patches) plugin.
469 |
470 | To add a patch to drupal module foobar insert the patches section in the extra
471 | section of composer.json:
472 | ```json
473 | "extra": {
474 | "patches": {
475 | "drupal/foobar": {
476 | "Patch description": "URL or local path to patch"
477 | }
478 | }
479 | }
480 | ```
481 | ### How do I switch from packagist.drupal-composer.org to packages.drupal.org?
482 |
483 | Follow the instructions in the [documentation on drupal.org](https://www.drupal.org/docs/develop/using-composer/using-packagesdrupalorg).
484 |
485 | ### How do I specify a PHP version ?
486 |
487 | This project supports PHP 5.6 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+.
488 |
489 | To prevent this you can add this code to specify the PHP version you want to use in the `config` section of `composer.json`:
490 | ```json
491 | "config": {
492 | "sort-packages": true,
493 | "platform": {
494 | "php": "5.6.40"
495 | }
496 | },
497 | ```
498 |
--------------------------------------------------------------------------------
/build.dist.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
45 |
46 |
47 |
48 |
49 |
50 | ${website.profile.name}
51 |
52 | install_configure_form.update_status_module='array(FALSE,FALSE)'
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
161 |
162 |
163 | user
164 |
165 |
166 |
167 |
168 |
169 |
174 |
175 |
176 | ${drupal.demo.user}
177 |
178 |
183 | ${drupal.demo.user}
184 | ${drupal.demo.user}
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
241 | ${module}
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
270 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
286 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
324 |
325 |
329 |
330 |
334 |
335 |
339 |
340 |
344 |
345 |
346 |
--------------------------------------------------------------------------------
/build.properties.dist:
--------------------------------------------------------------------------------
1 | # Drupal configuration
2 | # --------------------
3 |
4 | # The project name.
5 | project.name = myproject
6 |
7 | # The install profile to use.
8 | website.profile.name = standard
9 |
10 | # The site name.
11 | website.site.name = MyDrupalProject
12 |
13 | # Database settings.
14 | drupal.db.type = mysql
15 | drupal.db.name = ${project.name}
16 | drupal.db.user = root
17 | drupal.db.password =
18 | drupal.db.host = 127.0.0.1
19 | drupal.db.port = 3306
20 | drupal.db.url = ${drupal.db.type}://${drupal.db.user}:${drupal.db.password}@${drupal.db.host}:${drupal.db.port}/${drupal.db.name}
21 |
22 | # Admin user.
23 | drupal.admin.username = admin
24 | drupal.admin.password = admin
25 | drupal.admin.email = admin@example.com
26 |
27 | # Comma-separated list of demo users to create. The username and password will
28 | # be taken from the role. A normal authenticated user with username and password
29 | # 'user' will also be created.
30 | drupal.demo.users = administrator
31 |
32 | # The base URL. This is used for doing functional tests in Behat and PHPUnit.
33 | drupal.base_url = http://localhost
34 |
35 |
36 | # Paths
37 | # -----
38 |
39 | # Paths to executables.
40 | composer.bin = ${project.basedir}/vendor/bin/composer
41 | drush.bin = ${project.basedir}/vendor/bin/drush
42 | phing.bin = ${project.basedir}/vendor/bin/phing
43 |
44 | # Files and directories inside the Drupal installation.
45 | website.drupal.dir = ${project.basedir}/web
46 |
47 | website.sites.dir = ${website.drupal.dir}/sites
48 | website.site.dir = ${website.drupal.sites.dir}/all
49 |
50 | website.settings.dir = ${website.sites.dir}/default
51 | website.settings.php = ${website.settings.dir}/settings.php
52 | website.settings.local.php.example = ${website.sites.dir}/example.settings.local.php
53 | website.settings.local.php = ${website.settings.dir}/settings.local.php
54 | website.services.yml = ${website.settings.dir}/services.yml
55 | website.services.yml.default = ${website.settings.dir}/default.services.yml
56 | website.files.dir = ${website.settings.dir}/files
57 |
58 | website.modules.dir = ${website.drupal.dir}/modules
59 | website.profiles.dir = ${website.drupal.dir}/profiles
60 | website.themes.dir = ${website.drupal.dir}/themes
61 |
62 |
63 | # Behat configuration
64 | # -------------------
65 |
66 | # The location of the Behat executable.
67 | behat.bin = ${project.basedir}/vendor/bin/behat
68 |
69 | # The location of the Behat tests.
70 | behat.dir = ${project.basedir}/tests
71 |
72 | # The location of the Behat configuration template.
73 | behat.yml.template = ${behat.dir}/behat.yml.dist
74 |
75 | # The location of the generated Behat configuration file.
76 | behat.yml.path = ${behat.dir}/behat.yml
77 |
78 | # The base URL to use in Behat tests.
79 | behat.base_url = ${drupal.base_url}
80 |
81 | # The browser to use for testing, either 'firefox' or 'chrome'.
82 | behat.browser_name = chrome
83 |
84 | # The port of the webdriver host (e.g. Selenium or PhantomJS).
85 | behat.webdriver_port = 4444
86 |
87 | # The URL of the webdriver host (e.g. Selenium or PhantomJS).
88 | behat.webdriver_url = http://localhost:${behat.webdriver_port}/wd/hub
89 |
90 | # The location to search for Behat subcontexts.
91 | behat.subcontexts.path = ${website.modules.dir}
92 |
93 | # The output format to use for Behat tests, either 'progress' or 'pretty'.
94 | behat.formatter.name = progress
95 |
96 | # The location of the test files.
97 | behat.files.path = ${behat.dir}/fixtures/files
98 |
99 |
100 | # PHP CodeSniffer configuration
101 | # -----------------------------
102 |
103 | # The file extensions to test.
104 | phpcs.extensions = php inc module install info test profile theme css js
105 |
106 | # The default configuration file to generate.
107 | phpcs.config = ${project.basedir}/phpcs.xml
108 |
109 | # The coding standard to use. If you want to customize the rules, make a copy of
110 | # the file and name it 'phpcs-ruleset.xml'. Then copy this property to your
111 | # build.properties file and remove the '.dist' suffix.
112 | phpcs.standard = ${project.basedir}/phpcs-ruleset.xml.dist
113 |
114 | # Paths to check, delimited by semicolons.
115 | phpcs.files = ${website.modules.dir};${website.profiles.dir};${website.themes.dir}
116 |
117 | # Paths to ignore, delimited by semicolons.
118 | phpcs.ignore = ${website.modules.dir}/contrib
119 |
120 | # The report format. For example 'full', 'summary', 'diff', 'xml', 'json'.
121 | phpcs.report = full
122 |
123 | # Whether or not to show sniff codes in the report.
124 | phpcs.sniffcodes = 0
125 |
126 | # Whether or not to show the progress of the run.
127 | phpcs.progress = 1
128 |
129 | # The location of the file containing the global configuration options.
130 | phpcs.global.config = ${project.basedir}/vendor/squizlabs/php_codesniffer/CodeSniffer.conf
131 |
132 | # Whether or not to run a coding standards check before doing a git push. Note
133 | # that this will abort the push if the coding standards check fails.
134 | phpcs.prepush.enable = 0
135 |
136 | # The source and destination paths of the git pre-push hook.
137 | phpcs.prepush.source = ${project.basedir}/vendor/pfrenssen/phpcs-pre-push/pre-push
138 | phpcs.prepush.destination = ${project.basedir}/.git/hooks/pre-push
139 |
140 |
141 | # PHPUnit configuration
142 | # ---------------------
143 |
144 | # The path to the configuration file template.
145 | phpunit.dist = ${project.basedir}/phpunit.xml.dist
146 |
147 | # The path to the generated configuration file. This is typically inside the web
148 | # root.
149 | phpunit.config = ${website.drupal.dir}/phpunit.xml
150 |
151 | # The name to give to the test suite of the project.
152 | phpunit.testsuite.name = ${project.name}
153 |
154 | # Comma-separated list of directories containing tests to execute. These are
155 | # relative to the Drupal root.
156 | phpunit.directories = ./modules/custom,./profiles,./themes/custom
157 |
158 | # Comma-separated list of test files to execute. These are relative to the
159 | # Drupal root.
160 | phpunit.files =
161 |
162 | # The base URL to use in functional tests.
163 | phpunit.base_url = ${drupal.base_url}
164 |
165 | # The database URL to use in kernel tests and functional tests.
166 | phpunit.db_url = ${drupal.db.url}
167 |
168 | # The path to the directory where HTML output from browsertests is stored.
169 | phpunit.browsertest_output_dir = ${website.sites.dir}/simpletest/browser_output
170 |
171 | # The path to the file that lists HTML output from browsertests.
172 | phpunit.browsertest_output_file = ${phpunit.browsertest_output_dir}/outputfile.txt
173 |
174 |
175 | # Drush configuration
176 | # -------------------
177 |
178 | # The location of the Drush configuration folder.
179 | drush.dir = ${project.basedir}/drush
180 |
181 | # The location of the Drush configuration template.
182 | drush.yml.template = ${drush.dir}/drush.yml.dist
183 |
184 | # The location of the generated Drush configuration file.
185 | drush.yml.path = ${drush.dir}/drush.yml
186 |
187 | # Verbosity of Drush commands. Set to 'true' for verbose output.
188 | drush.verbose = false
189 |
190 |
191 | # Development options
192 | # -------------------
193 |
194 | # Development modules to enable.
195 | drupal.modules.dev = config_update devel field_ui menu_ui views_ui
196 |
197 | # Redirect outgoing e-mail to disk. This prevents e-mail from being
198 | # accidentally sent out on development machines. The mails can be found in the
199 | # folder temporary://devel-mails. This requires the devel module to be enabled.
200 | drupal.redirect.email = yes
201 |
--------------------------------------------------------------------------------
/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pfrenssen/drupal-project",
3 | "description": "Project template for Drupal 8 projects with Composer, Phing and Behat",
4 | "type": "project",
5 | "license": "GPL-2.0-or-later",
6 | "authors": [
7 | {
8 | "name": "",
9 | "role": ""
10 | }
11 | ],
12 | "repositories": [
13 | {
14 | "type": "composer",
15 | "url": "https://packages.drupal.org/8"
16 | },
17 | {
18 | "type": "package",
19 | "package": {
20 | "name": "pfrenssen/phpcs-pre-push",
21 | "version": "1.0",
22 | "type": "git-hook",
23 | "source": {
24 | "url": "https://gist.github.com/498fc52fea3f965f6640.git",
25 | "type": "git",
26 | "reference": "master"
27 | }
28 | }
29 | },
30 | {
31 | "type": "vcs",
32 | "url": "https://git.drupal.org/project/phingdrushtask.git"
33 | }
34 | ],
35 | "require": {
36 | "php": ">=5.6",
37 | "composer/composer": "~1.0",
38 | "composer/installers": "^1.2",
39 | "cweagans/composer-patches": "^1.6.5",
40 | "drupal-composer/drupal-scaffold": "^2.5",
41 | "drupal/console": "^1.0.2",
42 | "drupal/core": "^8.7.0",
43 | "drush/drush": "^9.0.0",
44 | "vlucas/phpdotenv": "^2.4",
45 | "webflo/drupal-finder": "^1.0.0",
46 | "webmozart/path-util": "^2.3",
47 | "zaporylie/composer-drupal-optimizations": "^1.0"
48 | },
49 | "require-dev": {
50 | "behat/mink": "~1.7",
51 | "behat/mink-goutte-driver": "~1.2",
52 | "behat/mink-selenium2-driver": "dev-master#721cbbaf37f71434f6acb604dc3a17a6a9be0c4c",
53 | "drupal/coder": "~8.2.7",
54 | "drupal/config_update": "1.*@dev",
55 | "drupal/devel": "1.*@dev",
56 | "drupal/drupal-extension": "~3.0",
57 | "drupal/phingdrushtask": "dev-7.x-2.x",
58 | "jcalderonzumba/gastonjs": "^1.1@dev",
59 | "jcalderonzumba/mink-phantomjs-driver": "~0.3.1",
60 | "mikey179/vfsStream": "~1.2",
61 | "pfrenssen/phpcs-pre-push": "1.0",
62 | "phing/phing": "~2.10",
63 | "phpunit/phpunit": ">=4.8.28 <5",
64 | "symfony/css-selector": "~2.8|~3.0|~4.0",
65 | "webflo/drupal-core-require-dev": "^8.7.0"
66 | },
67 | "conflict": {
68 | "drupal/drupal": "*"
69 | },
70 | "minimum-stability": "dev",
71 | "prefer-stable": true,
72 | "config": {
73 | "sort-packages": true,
74 | "platform": {
75 | "php": "5.6.31"
76 | }
77 | },
78 | "autoload": {
79 | "psr-4": {
80 | "Drupal\\DrupalProject\\": "tests/src",
81 | "DrupalProject\\": "src"
82 | },
83 | "classmap": [
84 | "scripts/composer/ScriptHandler.php"
85 | ],
86 | "files": ["load.environment.php"]
87 | },
88 | "scripts": {
89 | "pre-install-cmd": [
90 | "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
91 | ],
92 | "pre-update-cmd": [
93 | "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
94 | ],
95 | "post-install-cmd": [
96 | "DrupalProject\\composer\\ScriptHandler::createRequiredFiles"
97 | ],
98 | "post-update-cmd": [
99 | "DrupalProject\\composer\\ScriptHandler::createRequiredFiles"
100 | ]
101 | },
102 | "extra": {
103 | "composer-exit-on-patch-failure": true,
104 | "patchLevel": {
105 | "drupal/core": "-p2"
106 | },
107 | "installer-paths": {
108 | "web/core": ["type:drupal-core"],
109 | "web/libraries/{$name}": ["type:drupal-library"],
110 | "web/modules/contrib/{$name}": ["type:drupal-module"],
111 | "web/profiles/contrib/{$name}": ["type:drupal-profile"],
112 | "web/themes/contrib/{$name}": ["type:drupal-theme"],
113 | "drush/Commands/{$name}": ["type:drupal-drush"]
114 | },
115 | "drupal-scaffold": {
116 | "initial": {
117 | ".editorconfig": "../.editorconfig",
118 | ".gitattributes": "../.gitattributes"
119 | }
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/drush/Commands/PolicyCommands.php:
--------------------------------------------------------------------------------
1 | input()->getArgument('target') == '@prod') {
22 | throw new \Exception(dt('Per !file, you may never overwrite the production database.', ['!file' => __FILE__]));
23 | }
24 | }
25 |
26 | /**
27 | * Limit rsync operations to production site.
28 | *
29 | * @hook validate core:rsync
30 | *
31 | * @throws \Exception
32 | */
33 | public function rsyncValidate(CommandData $commandData) {
34 | if (preg_match("/^@prod/", $commandData->input()->getArgument('target'))) {
35 | throw new \Exception(dt('Per !file, you may never rsync to the production site.', ['!file' => __FILE__]));
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/drush/README.md:
--------------------------------------------------------------------------------
1 | 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.
2 |
--------------------------------------------------------------------------------
/drush/drush.yml.dist:
--------------------------------------------------------------------------------
1 | # The Drush configuration file
2 | #
3 | # Docs at https://github.com/drush-ops/drush/blob/master/examples/example.drush.yml
4 |
5 | options:
6 | uri: '${drupal.base_url}'
7 | verbose: ${drush.verbose}
8 |
--------------------------------------------------------------------------------
/drush/sites/self.site.yml:
--------------------------------------------------------------------------------
1 | # Edit or remove this file as needed.
2 | # Docs at https://github.com/drush-ops/drush/blob/master/examples/example.site.yml
3 |
4 | #prod:
5 | # host: prod.domain.com
6 | # user: www-admin
7 | # root: /path/to/drupal
8 | # uri: http://www.example.com
9 | #
10 | #stage:
11 | # host: stage.domain.com
12 | # user: www-admin
13 | # root: /path/to/drupal
14 | # uri: http://stage.example.com
15 |
--------------------------------------------------------------------------------
/load.environment.php:
--------------------------------------------------------------------------------
1 | load();
17 | }
18 | catch (InvalidPathException $e) {
19 | // Do nothing. Production environments rarely use .env files.
20 | }
21 |
--------------------------------------------------------------------------------
/phpcs-ruleset.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Drupal coding standard
6 |
7 |
8 | *.gif
9 | *.less
10 | *.png
11 |
12 |
13 | *.min.css
14 | *.min.js
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | ./core/includes
41 | ./core/lib
42 | ./core/modules
43 | ./modules
44 | ./sites
45 |
46 |
47 | ./
48 | ./
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/scripts/composer/ScriptHandler.php:
--------------------------------------------------------------------------------
1 | locateRoot(getcwd());
22 | $drupalRoot = $drupalFinder->getDrupalRoot();
23 |
24 | $dirs = [
25 | 'modules',
26 | 'profiles',
27 | 'themes',
28 | ];
29 |
30 | // Required for unit testing
31 | foreach ($dirs as $dir) {
32 | if (!$fs->exists($drupalRoot . '/'. $dir)) {
33 | $fs->mkdir($drupalRoot . '/'. $dir);
34 | $fs->touch($drupalRoot . '/'. $dir . '/.gitkeep');
35 | }
36 | }
37 |
38 | // Prepare the settings file for installation
39 | if (!$fs->exists($drupalRoot . '/sites/default/settings.php') and $fs->exists($drupalRoot . '/sites/default/default.settings.php')) {
40 | $fs->copy($drupalRoot . '/sites/default/default.settings.php', $drupalRoot . '/sites/default/settings.php');
41 | require_once $drupalRoot . '/core/includes/bootstrap.inc';
42 | require_once $drupalRoot . '/core/includes/install.inc';
43 | $settings['config_directories'] = [
44 | CONFIG_SYNC_DIRECTORY => (object) [
45 | 'value' => Path::makeRelative($drupalFinder->getComposerRoot() . '/config/sync', $drupalRoot),
46 | 'required' => TRUE,
47 | ],
48 | ];
49 | drupal_rewrite_settings($settings, $drupalRoot . '/sites/default/settings.php');
50 | $fs->chmod($drupalRoot . '/sites/default/settings.php', 0640);
51 | $event->getIO()->write("Created a sites/default/settings.php file with chmod 0640");
52 | }
53 |
54 | // Create the files directory with chmod 0755
55 | if (!$fs->exists($drupalRoot . '/sites/default/files')) {
56 | $oldmask = umask(0);
57 | $fs->mkdir($drupalRoot . '/sites/default/files', 0755);
58 | umask($oldmask);
59 | $event->getIO()->write("Created a sites/default/files directory with chmod 0755");
60 | }
61 | }
62 |
63 | /**
64 | * Checks if the installed version of Composer is compatible.
65 | *
66 | * Composer 1.0.0 and higher consider a `composer install` without having a
67 | * lock file present as equal to `composer update`. We do not ship with a lock
68 | * file to avoid merge conflicts downstream, meaning that if a project is
69 | * installed with an older version of Composer the scaffolding of Drupal will
70 | * not be triggered. We check this here instead of in drupal-scaffold to be
71 | * able to give immediate feedback to the end user, rather than failing the
72 | * installation after going through the lengthy process of compiling and
73 | * downloading the Composer dependencies.
74 | *
75 | * @see https://github.com/composer/composer/pull/5035
76 | */
77 | public static function checkComposerVersion(Event $event) {
78 | $composer = $event->getComposer();
79 | $io = $event->getIO();
80 |
81 | $version = $composer::VERSION;
82 |
83 | // The dev-channel of composer uses the git revision as version number,
84 | // try to the branch alias instead.
85 | if (preg_match('/^[0-9a-f]{40}$/i', $version)) {
86 | $version = $composer::BRANCH_ALIAS_VERSION;
87 | }
88 |
89 | // If Composer is installed through git we have no easy way to determine if
90 | // it is new enough, just display a warning.
91 | if ($version === '@package_version@' || $version === '@package_branch_alias_version@') {
92 | $io->writeError('You are running a development version of Composer. If you experience problems, please update Composer to the latest stable version.');
93 | }
94 | elseif (Comparator::lessThan($version, '1.0.0')) {
95 | $io->writeError('Drupal-project requires Composer version 1.0.0 or higher. Please update your Composer before continuing.');
96 | exit(1);
97 | }
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/scripts/travis-ci/run-test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | case "$1" in
4 | PHP_CodeSniffer)
5 | cd $TRAVIS_BUILD_DIR
6 | ./vendor/bin/phpcs
7 | exit $?
8 | ;;
9 | PHPUnit)
10 | cd $TRAVIS_BUILD_DIR/web
11 | ../vendor/bin/phpunit
12 | exit $?
13 | ;;
14 | Behat)
15 | cd $TRAVIS_BUILD_DIR/tests
16 | ./behat
17 | exit $?
18 | ;;
19 | *)
20 | echo "Unknown test '$1'"
21 | exit 1
22 | esac
23 |
--------------------------------------------------------------------------------
/src/Phing/PhpCodeSnifferConfigurationTask.php:
--------------------------------------------------------------------------------
1 | checkRequirements();
86 |
87 | $document = new \DOMDocument('1.0', 'UTF-8');
88 | $document->formatOutput = TRUE;
89 |
90 | // Create the root 'ruleset' element.
91 | $root_element = $document->createElement('ruleset');
92 | $root_element->setAttribute('name', 'pbm_default');
93 | $document->appendChild($root_element);
94 |
95 | // Add the description.
96 | $element = $document->createElement('description', 'Default PHP CodeSniffer configuration for composer based Drupal projects.');
97 | $root_element->appendChild($element);
98 |
99 | // Add the coding standard.
100 | $element = $document->createElement('rule');
101 | $element->setAttribute('ref', $this->standard);
102 | $root_element->appendChild($element);
103 |
104 | // Add the files to check.
105 | foreach ($this->files as $file) {
106 | $element = $document->createElement('file', $file);
107 | $root_element->appendChild($element);
108 | }
109 |
110 | // Add file extensions.
111 | if (!empty($this->extensions)) {
112 | $extensions = implode(',', $this->extensions);
113 | $this->appendArgument($document, $root_element, $extensions, 'extensions');
114 | }
115 |
116 | // Add ignore patterns.
117 | foreach ($this->ignorePatterns as $pattern) {
118 | $element = $document->createElement('exclude-pattern', $pattern);
119 | $root_element->appendChild($element);
120 | }
121 |
122 | // Add the report type.
123 | if (!empty($this->report)) {
124 | $this->appendArgument($document, $root_element, $this->report, 'report');
125 | }
126 |
127 | // Add the shorthand options.
128 | $shorthand_options = array(
129 | 'p' => 'showProgress',
130 | 's' => 'showSniffCodes',
131 | );
132 |
133 | $options = array_filter($shorthand_options, function ($value) {
134 | return $this->$value;
135 | });
136 |
137 | if (!empty($options)) {
138 | $this->appendArgument($document, $root_element, implode('', array_flip($options)));
139 | }
140 |
141 | // Save the file.
142 | file_put_contents($this->configFile, $document->saveXML());
143 |
144 | // If a global configuration file is passed, update this too.
145 | if (!empty($this->globalConfig)) {
146 | $global_config = << '$this->configFile',
150 | );
151 | PHP;
152 | file_put_contents($this->globalConfig, $global_config);
153 | }
154 | }
155 |
156 | /**
157 | * Appends an argument element to the XML document.
158 | *
159 | * This will append an XML element in the following format:
160 | *
161 | *
162 | * @param \DOMDocument $document
163 | * The document that will contain the argument to append.
164 | * @param \DOMElement $element
165 | * The parent element of the argument to append.
166 | * @param string $value
167 | * The argument value.
168 | * @param string $name
169 | * Optional argument name.
170 | */
171 | protected function appendArgument(\DOMDocument $document, \DOMElement $element, $value, $name = '') {
172 | $argument = $document->createElement('arg');
173 | if (!empty($name)) {
174 | $argument->setAttribute('name', $name);
175 | }
176 | $argument->setAttribute('value', $value);
177 | $element->appendChild($argument);
178 | }
179 |
180 | /**
181 | * Checks if all properties required for generating the config are present.
182 | *
183 | * @throws \BuildException
184 | * Thrown when a required property is not present.
185 | */
186 | protected function checkRequirements() {
187 | $required_properties = array('configFile', 'files', 'standard');
188 | foreach ($required_properties as $required_property) {
189 | if (empty($this->$required_property)) {
190 | throw new \BuildException("Missing required property '$required_property'.");
191 | }
192 | }
193 | }
194 |
195 | /**
196 | * Sets the path to the configuration file to generate.
197 | *
198 | * @param string $configFile
199 | * The path to the configuration file to generate.
200 | */
201 | public function setConfigFile($configFile) {
202 | $this->configFile = $configFile;
203 | }
204 |
205 | /**
206 | * Sets the file extensions to scan.
207 | *
208 | * @param string $extensions
209 | * A string containing file extensions, delimited by spaces, commas or
210 | * semicolons.
211 | */
212 | public function setExtensions($extensions) {
213 | $this->extensions = array();
214 | $token = ' ,;';
215 | $extension = strtok($extensions, $token);
216 | while ($extension !== false) {
217 | $this->extensions[] = $extension;
218 | $extension = strtok($token);
219 | }
220 | }
221 |
222 | /**
223 | * Sets the list of files and folders to scan.
224 | *
225 | * @param string $files
226 | * A list of paths, delimited by spaces, commas or semicolons.
227 | */
228 | public function setFiles($files) {
229 | $this->files = array();
230 | $token = ' ,;';
231 | $file = strtok($files, $token);
232 | while ($file !== false) {
233 | $this->files[] = $file;
234 | $file = strtok($token);
235 | }
236 | }
237 |
238 | /**
239 | * Sets the path to the global configuration file to generate.
240 | *
241 | * @param string $globalConfig
242 | * The path to the global configuration file to generate.
243 | */
244 | public function setGlobalConfig($globalConfig) {
245 | $this->globalConfig = $globalConfig;
246 | }
247 |
248 | /**
249 | * Sets the list of patterns to ignore.
250 | *
251 | * @param string $ignorePatterns
252 | * The list of patterns, delimited by spaces, commas or semicolons.
253 | */
254 | public function setIgnorePatterns($ignorePatterns) {
255 | $this->ignorePatterns = array();
256 | $token = ' ,;';
257 | $pattern = strtok($ignorePatterns, $token);
258 | while ($pattern !== false) {
259 | $this->ignorePatterns[] = $pattern;
260 | $pattern = strtok($token);
261 | }
262 | }
263 |
264 | /**
265 | * Sets the report format to use.
266 | *
267 | * @param string $report
268 | * The report format to use.
269 | */
270 | public function setReport($report) {
271 | $this->report = $report;
272 | }
273 |
274 | /**
275 | * Sets whether or not to show progress.
276 | *
277 | * @param bool $showProgress
278 | * Whether or not to show progress.
279 | */
280 | public function setShowProgress($showProgress) {
281 | $this->showProgress = (bool) $showProgress;
282 | }
283 |
284 | /**
285 | * Sets whether or not to show sniff codes in the report.
286 | *
287 | * @param bool $showSniffCodes
288 | * Whether or not to show sniff codes.
289 | */
290 | public function setShowSniffCodes($showSniffCodes) {
291 | $this->showSniffCodes = (bool) $showSniffCodes;
292 | }
293 |
294 | /**
295 | * Sets the coding standard to use.
296 | *
297 | * @param string $standard
298 | * The coding standard to use.
299 | */
300 | public function setStandard($standard) {
301 | $this->standard = $standard;
302 | }
303 |
304 | }
305 |
--------------------------------------------------------------------------------
/src/Phing/PhpUnitConfigurationTask.php:
--------------------------------------------------------------------------------
1 | checkRequirements();
86 |
87 | // Load the template file.
88 | $document = new \DOMDocument('1.0', 'UTF-8');
89 | $document->preserveWhiteSpace = FALSE;
90 | $document->formatOutput = TRUE;
91 | $document->load($this->distFile);
92 |
93 | // Set the base URL.
94 | $this->setEnvironmentVariable('SIMPLETEST_BASE_URL', $this->baseUrl, $document);
95 |
96 | // Set the database URL.
97 | $this->setEnvironmentVariable('SIMPLETEST_DB', $this->dbUrl, $document);
98 |
99 | // Set the path to the browsertest output directory.
100 | $this->setEnvironmentVariable('BROWSERTEST_OUTPUT_DIRECTORY', $this->browsertestOutputDirectory, $document);
101 |
102 | // Set the path to the browsertest output file.
103 | $this->setEnvironmentVariable('BROWSERTEST_OUTPUT_FILE', $this->browsertestOutputFile, $document);
104 |
105 | // Add a test suite for the Drupal project.
106 | $test_suite = $document->createElement('testsuite');
107 | $test_suite->setAttribute('name', $this->testsuiteName);
108 |
109 | // Append the list of test files.
110 | foreach ($this->files as $file) {
111 | $element = $document->createElement('file', $file);
112 | $test_suite->appendChild($element);
113 | }
114 |
115 | // Append the list of test directories.
116 | foreach ($this->directories as $directory) {
117 | $element = $document->createElement('directory', $directory);
118 | $test_suite->appendChild($element);
119 | }
120 |
121 | // Insert the test suite in the list of test suites.
122 | $test_suites = $document->getElementsByTagName('testsuites')->item(0);
123 | $test_suites->appendChild($test_suite);
124 |
125 | // Save the file.
126 | file_put_contents($this->configFile, $document->saveXML());
127 | }
128 |
129 | /**
130 | * Sets the value of a pre-existing environment variable.
131 | *
132 | * @param string $variableName
133 | * The name of the environment variable for which to set the value.
134 | * @param string $value
135 | * The value to set.
136 | * @param \DOMDocument $document
137 | * The document in which the change should take place.
138 | */
139 | protected function setEnvironmentVariable($variableName, $value, \DOMDocument $document) {
140 | /** @var \DOMElement $element */
141 | foreach ($document->getElementsByTagName('env') as $element) {
142 | if ($element->getAttribute('name') === $variableName) {
143 | $element->setAttribute('value', $value);
144 | break;
145 | }
146 | }
147 | }
148 | /**
149 | * Checks if all properties required for generating the config are present.
150 | *
151 | * @throws \BuildException
152 | * Thrown when a required property is not present.
153 | */
154 | protected function checkRequirements() {
155 | $required_properties = ['configFile', 'distFile'];
156 | foreach ($required_properties as $required_property) {
157 | if (empty($this->$required_property)) {
158 | throw new \BuildException("Missing required property '$required_property'.");
159 | }
160 | }
161 | }
162 |
163 | /**
164 | * Sets the path to the template of the configuration file.
165 | *
166 | * @param string $distFile
167 | * The path to the template of the configuration file.
168 | */
169 | public function setDistFile($distFile) {
170 | $this->distFile = $distFile;
171 | }
172 |
173 | /**
174 | * Sets the path to the configuration file to generate.
175 | *
176 | * @param string $configFile
177 | * The path to the configuration file to generate.
178 | */
179 | public function setConfigFile($configFile) {
180 | $this->configFile = $configFile;
181 | }
182 |
183 | /**
184 | * Sets the list of directories containing test files to execute.
185 | *
186 | * @param string $directories
187 | * A list of directory paths, delimited by spaces, commas or semicolons.
188 | */
189 | public function setDirectories($directories) {
190 | $this->directories = [];
191 | $token = ' ,;';
192 | $directory = strtok($directories, $token);
193 | while ($directory !== FALSE) {
194 | $this->directories[] = $directory;
195 | $directory = strtok($token);
196 | }
197 | }
198 |
199 | /**
200 | * Sets the list of test files to execute.
201 | *
202 | * @param string $files
203 | * A list of file paths, delimited by spaces, commas or semicolons.
204 | */
205 | public function setFiles($files) {
206 | $this->files = [];
207 | $token = ' ,;';
208 | $file = strtok($files, $token);
209 | while ($file !== FALSE) {
210 | $this->files[] = $file;
211 | $file = strtok($token);
212 | }
213 | }
214 |
215 | /**
216 | * Sets the name of the test suite.
217 | *
218 | * @param string $testsuiteName
219 | * The name of the test suite.
220 | */
221 | public function setTestsuiteName($testsuiteName) {
222 | $this->testsuiteName = $testsuiteName;
223 | }
224 |
225 | /**
226 | * Sets the base URL.
227 | *
228 | * @param string $baseUrl
229 | * The base URL.
230 | */
231 | public function setBaseUrl($baseUrl) {
232 | $this->baseUrl = $baseUrl;
233 | }
234 |
235 | /**
236 | * Sets the database URL.
237 | *
238 | * @param string $dbUrl
239 | * The database URL.
240 | */
241 | public function setDbUrl($dbUrl) {
242 | $this->dbUrl = $dbUrl;
243 | }
244 |
245 | /**
246 | * Sets the path to the browsertest output directory.
247 | *
248 | * @param string $browsertestOutputDirectory
249 | * The path to the directory.
250 | */
251 | public function setBrowsertestOutputDirectory($browsertestOutputDirectory) {
252 | $this->browsertestOutputDirectory = $browsertestOutputDirectory;
253 | }
254 |
255 | /**
256 | * Sets the path to the browsertest output file.
257 | *
258 | * @param string $browsertestOutputFile
259 | * The path to the file.
260 | */
261 | public function setBrowsertestOutputFile($browsertestOutputFile) {
262 | $this->browsertestOutputFile = $browsertestOutputFile;
263 | }
264 |
265 | }
266 |
--------------------------------------------------------------------------------
/tests/behat:
--------------------------------------------------------------------------------
1 | ../vendor/bin/behat
--------------------------------------------------------------------------------
/tests/behat.yml.dist:
--------------------------------------------------------------------------------
1 | default:
2 | suites:
3 | default:
4 | contexts:
5 | - FeatureContext
6 | - Drupal\DrupalExtension\Context\DrupalContext
7 | - Drupal\DrupalExtension\Context\DrushContext
8 | - Drupal\DrupalExtension\Context\MessageContext
9 | - Drupal\DrupalExtension\Context\MinkContext
10 | filters:
11 | tags: '~@wip'
12 | extensions:
13 | Behat\MinkExtension:
14 | base-url: '${behat.base_url}'
15 | files_path: '${behat.files.path}'
16 | goutte: ~
17 | javascript_session: 'selenium2'
18 | browser_name: '${behat.browser_name}'
19 | selenium2:
20 | wd_host: '${behat.webdriver_url}'
21 | Drupal\DrupalExtension:
22 | api_driver: 'drupal'
23 | blackbox: ~
24 | drupal:
25 | drupal_root: '${website.drupal.dir}'
26 | selectors:
27 | message_selector: '.messages'
28 | error_message_selector: '.messages.messages--error'
29 | success_message_selector: '.messages.messages--status'
30 | subcontexts:
31 | paths:
32 | - '${behat.subcontexts.path}'
33 | formatters:
34 | ${behat.formatter.name}: ~
35 |
--------------------------------------------------------------------------------
/tests/features/authentication.feature:
--------------------------------------------------------------------------------
1 | Feature: User authentication
2 | In order to protect the integrity of the website
3 | As a product owner
4 | I want to make sure only authenticated users can access the site administration
5 |
6 | Scenario: Anonymous user can see the user login page
7 | Given I am not logged in
8 | When I visit "user"
9 | Then I should see the text "Log in"
10 | And I should see the text "Reset your password"
11 | And I should see the text "Username"
12 | And I should see the text "Password"
13 | But I should not see the text "Log out"
14 | And I should not see the text "My account"
15 |
16 | Scenario Outline: Anonymous user cannot access site administration
17 | Given I am not logged in
18 | When I go to ""
19 | Then I should get an access denied error
20 |
21 | Examples:
22 | | path |
23 | | admin |
24 | | admin/config |
25 | | admin/content |
26 | | admin/people |
27 | | admin/structure |
28 | | node/add |
29 | | node/add/page |
30 |
--------------------------------------------------------------------------------
/tests/features/bootstrap/FeatureContext.php:
--------------------------------------------------------------------------------
1 | assertSession()->statusCodeEquals(403);
23 | }
24 |
25 | /**
26 | * Checks that a given image is present in the page.
27 | *
28 | * @Then I (should )see the image :filename
29 | */
30 | public function assertImagePresent($filename) {
31 | // Drupal appends an underscore and a number to the filename when duplicate
32 | // files are uploaded, for example when a test is run more than once.
33 | // We split up the filename and extension and match for both.
34 | $parts = pathinfo($filename);
35 | $extension = $parts['extension'];
36 | $filename = $parts['filename'];
37 | $this->assertSession()->elementExists('css', "img[src$='.$extension'][src*='$filename']");
38 | }
39 |
40 | /**
41 | * Checks that a given image is not present in the page.
42 | *
43 | * @Then I should not see the image :filename
44 | */
45 | public function assertImageNotPresent($filename) {
46 | // Drupal appends an underscore and a number to the filename when duplicate
47 | // files are uploaded, for example when a test is run more than once.
48 | // We split up the filename and extension and match for both.
49 | $parts = pathinfo($filename);
50 | $extension = $parts['extension'];
51 | $filename = $parts['filename'];
52 | $this->assertSession()->elementNotExists('css', "img[src$='.$extension'][src*='$filename']");
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------