├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── RoboFile.php
├── composer.json
├── src
├── DrushStack.php
└── loadTasks.php
└── tests
└── DrushStackTest.php
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor/
2 | /.idea/
3 | composer.lock
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | php:
3 | - 7.2
4 | - 7.1
5 | - 7.0
6 | - 5.6
7 | install:
8 | - composer self-update
9 | - composer install
10 | script:
11 | - vendor/bin/robo test
12 |
13 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [Unreleased][unreleased]
9 |
10 | ## [4.2.0] - 2018-12-11
11 |
12 | ### Added
13 |
14 | - `existingConfig` method for site installs (which sets `--existing-config` in the drush call)
15 |
16 | ## [4.1.0] - 2018-09-11
17 |
18 | ### Added
19 |
20 | - possibility to test multiple drush versions
21 |
22 | ## [4.0.0] - 2018-09-11
23 |
24 | Since people might have shell escaped these parameters already,
25 | this version is a new major as it is potentially backwards incompatible.
26 |
27 | ### Changed
28 |
29 | - `accountPass` and `dbSuPw` in site install command are now shell escaped
30 |
31 | ## [3.1.1] - 2017-08-21
32 |
33 | ### Added
34 |
35 | - support for the upcoming Drush 9 (only use `drush version` to get the version)
36 |
37 | ## [3.1.0] - 2017-07-05
38 |
39 | ### Added
40 |
41 | - support for `config-dir` property
42 |
43 | ## [3.0.2] - 2017-02-01
44 |
45 | ### Changed
46 |
47 | - consolidation/robo dependency to `~1`
48 |
49 | ## [2.2.1] - 2015-11-27
50 |
51 | ### Changed
52 |
53 | - Robo dependency to `>=0.5.2`, which means all future versions. As Robo is in pre-1.0 stage, this seems to make sense.
54 |
55 | ## [2.2.0] - 2015-09-20
56 |
57 | ### Added
58 |
59 | - second parameter `assumeYes` (default `true`) to `exec()`
60 |
61 | ## [2.1.0] - 2015-02-27
62 |
63 | This version is the first one working without strict errors using Robo >=0.5.2.
64 |
65 | ### Added
66 |
67 | - Robo dependency to `~0.5.2` (and removed `conflict` section)
68 |
69 | ### Fixed
70 |
71 | - PSR-4 autoloading (renamed `Drush.php` to `DrushStack.php`
72 | - PHPUnit deprecation warning
73 |
74 | ## [2.0.2] - 2015-02-21
75 |
76 | You have to use `"codegyre/robo": "dev-master"` in your composer.json,
77 | since there is no new release which includes https://github.com/Codegyre/Robo/pull/114.
78 |
79 | ### Fixed
80 |
81 | - strict warning about 'same property'
82 |
83 | ## [2.0.1] - 2015-01-25
84 |
85 | ### Fixed
86 |
87 | - Robo version in `conflict` section of composer.json
88 |
89 | ## [2.0.0] - 2015-01-25
90 |
91 | Release for Robo >=0.5 (not compatible with 0.4.*!).
92 |
93 | ### Changed
94 |
95 | - Trait name to `\Boedah\Robo\Task\Drush\loadTasks` in line with Robo tasks
96 | - Task name from `DrushStackTask` to `DrushStack`
97 |
98 | ## [1.0.3] - 2015-01-25
99 |
100 | ### Added
101 |
102 | - `conflict` section in composer.json
103 |
104 | ## [1.0.2] - 2015-01-25
105 |
106 | ### Added
107 | - This [change log](CHANGELOG.md) following [keepachangelog.com](http://keepachangelog.com/).
108 | - Installation instructions to [README](README.md).
109 |
110 | ### Changed
111 | - Robo version in composer dev dependencies is now 0.4.5, as 0.4.6. introduced a BC break.
112 | Code will be updated soon to be compatible with Robo 0.5.
113 |
114 | ### Fixed
115 | - phpdoc of `getVersion()`
116 |
117 | ## [1.0.1] - 2014-06-20
118 |
119 | ### Fixed
120 | - Drush version is now fetched correctly in `updateDb()`
121 |
122 | ## 1.0.0 - 2014-06-06
123 |
124 | ### Added
125 | - Initial commit
126 |
127 | [unreleased]: https://github.com/boedah/robo-drush/compare/4.2.0...HEAD
128 | [1.0.1]: https://github.com/boedah/robo-drush/compare/1.0.0...1.0.1
129 | [1.0.2]: https://github.com/boedah/robo-drush/compare/1.0.1...1.0.2
130 | [1.0.3]: https://github.com/boedah/robo-drush/compare/1.0.2...1.0.3
131 | [2.0.0]: https://github.com/boedah/robo-drush/compare/1.0.3...2.0.0
132 | [2.0.1]: https://github.com/boedah/robo-drush/compare/2.0.0...2.0.1
133 | [2.0.2]: https://github.com/boedah/robo-drush/compare/2.0.1...2.0.2
134 | [2.1.0]: https://github.com/boedah/robo-drush/compare/2.0.2...2.1.0
135 | [2.2.0]: https://github.com/boedah/robo-drush/compare/2.1.0...2.2.0
136 | [2.2.1]: https://github.com/boedah/robo-drush/compare/2.2.0...2.2.1
137 | [3.0.2]: https://github.com/boedah/robo-drush/compare/2.2.1...3.0.2
138 | [3.1.0]: https://github.com/boedah/robo-drush/compare/3.0.2...3.1.0
139 | [3.1.1]: https://github.com/boedah/robo-drush/compare/3.1.0...3.1.1
140 | [4.0.0]: https://github.com/boedah/robo-drush/compare/3.1.1...4.0.0
141 | [4.1.0]: https://github.com/boedah/robo-drush/compare/4.0.0...4.1.0
142 | [4.2.0]: https://github.com/boedah/robo-drush/compare/4.1.0...4.2.0
143 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Robo Drush Extension
2 |
3 | Extension to execute Drush commands in [Robo](https://github.com/Codegyre/Robo).
4 |
5 | [](https://insight.sensiolabs.com/projects/1d842f01-b2c4-415a-b372-12af7a5516e0) [](https://travis-ci.org/boedah/robo-drush) [](https://packagist.org/packages/boedah/robo-drush) [](https://packagist.org/packages/boedah/robo-drush) [](https://packagist.org/packages/boedah/robo-drush) [](https://packagist.org/packages/boedah/robo-drush)
6 |
7 | Runs Drush commands in stack. You can define global options for all commands (like Drupal root and uri).
8 |
9 | The option -y assumed by default but can be overridden on calls to `exec()` by passing `false` as the second parameter.
10 |
11 | ## Table of contents
12 |
13 | - [Versions](#versions)
14 | - [Installation](#installation)
15 | - [Testing](#testing)
16 | - [Usage](#usage)
17 | - [Examples](#examples)
18 |
19 | ## Installation
20 |
21 | For new projects (and Robo >= 1.0.0-RC1), just do:
22 |
23 | composer require --dev boedah/robo-drush
24 |
25 | For older versions of Robo, use:
26 |
27 | - `~1.0`: Robo <= 0.4.5
28 | - `~2.1`: Robo >= 0.5.2
29 |
30 | ## Testing
31 |
32 | `composer test`
33 |
34 | ## Usage
35 |
36 | Use the trait (according to your used version) in your RoboFile:
37 |
38 | ```php
39 | class RoboFile extends \Robo\Tasks
40 | {
41 | // if you use robo-drush ~2.1 for Robo >=0.5.2, or robo-drush >3 for Robo >=1.0.0-RC1
42 | use \Boedah\Robo\Task\Drush\loadTasks;
43 |
44 | // if you use ~1.0 for Robo ~0.4
45 | use \Boedah\Robo\Task\Drush;
46 |
47 | //...
48 | }
49 | ```
50 |
51 | ## Examples
52 |
53 | ### Site update
54 |
55 | This executes pending database updates and reverts all features (from code to database):
56 |
57 | ```php
58 | $this->taskDrushStack()
59 | ->drupalRootDirectory('/var/www/html/some-site')
60 | ->uri('sub.example.com')
61 | ->maintenanceOn()
62 | ->updateDb()
63 | ->revertAllFeatures()
64 | ->maintenanceOff()
65 | ->run();
66 | ```
67 |
68 | ### Site install
69 |
70 | ```php
71 | $this->taskDrushStack()
72 | ->siteName('Site Name')
73 | ->siteMail('site-mail@example.com')
74 | ->locale('de')
75 | ->accountMail('mail@example.com')
76 | ->accountName('admin')
77 | ->accountPass('pw')
78 | ->dbPrefix('drupal_')
79 | ->sqliteDbUrl('sites/default/.ht.sqlite')
80 | ->disableUpdateStatusModule()
81 | ->siteInstall('minimal')
82 | ->run();
83 | ```
84 |
--------------------------------------------------------------------------------
/RoboFile.php:
--------------------------------------------------------------------------------
1 | stopOnFail(true);
10 | $this->taskPHPUnit()
11 | ->option('disallow-test-output')
12 | ->option('report-useless-tests')
13 | ->option('strict-coverage')
14 | ->option('-v')
15 | ->option('-d error_reporting=-1')
16 | ->bootstrap('vendor/autoload.php')
17 | ->arg('tests')
18 | ->run();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "boedah/robo-drush",
3 | "description": "Drush CommandStack for Robo Task Runner",
4 | "type": "robo-tasks",
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "Peter Gasser",
9 | "email": "dev@boedah.de"
10 | }
11 | ],
12 | "scripts": {
13 | "test": "robo --ansi test"
14 | },
15 | "autoload": {
16 | "psr-4": {
17 | "Boedah\\Robo\\Task\\Drush\\": "src"
18 | }
19 | },
20 | "require": {
21 | "php": ">=5.5.0",
22 | "consolidation/robo": "~1"
23 | },
24 | "require-dev": {
25 | "phpunit/phpunit": "~4.4",
26 | "drush/drush": "^8.0 | ^9.0"
27 | },
28 | "suggest": {
29 | "drush/drush": "robo-drush needs a global or local Drush to use."
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/DrushStack.php:
--------------------------------------------------------------------------------
1 | taskDrushStack()
15 | * ->drupalRootDirectory('/var/www/html/some-site')
16 | * ->uri('sub.example.com')
17 | * ->maintenanceOn()
18 | * ->updateDb()
19 | * ->revertAllFeatures()
20 | * ->maintenanceOff()
21 | * ->run();
22 | * ```
23 | *
24 | * Example site install command:
25 | *
26 | * ``` php
27 | * $this->taskDrushStack()
28 | * ->siteName('Site Name')
29 | * ->siteMail('site-mail@example.com')
30 | * ->locale('de')
31 | * ->accountMail('mail@example.com')
32 | * ->accountName('admin')
33 | * ->accountPass('pw')
34 | * ->dbPrefix('drupal_')
35 | * ->sqliteDbUrl('sites/default/.ht.sqlite')
36 | * ->disableUpdateStatusModule()
37 | * ->siteInstall('minimal')
38 | * ->run();
39 | * ```
40 | */
41 | class DrushStack extends CommandStack
42 | {
43 | use CommandArguments;
44 |
45 | protected $argumentsForNextCommand;
46 |
47 | /**
48 | * Drush site alias.
49 | * We need to save this, since it needs to be the first argument.
50 | *
51 | * @var string
52 | */
53 | protected $siteAlias;
54 |
55 | /**
56 | * @var string
57 | */
58 | protected $drushVersion;
59 |
60 | public function __construct($pathToDrush = 'drush')
61 | {
62 | $this->executable = $pathToDrush;
63 | }
64 |
65 | public function drupalRootDirectory($drupalRootDirectory)
66 | {
67 | $this->printTaskInfo('Drupal root: ' . $drupalRootDirectory . '');
68 | $this->option('-r', $drupalRootDirectory);
69 |
70 | return $this;
71 | }
72 |
73 | public function uri($uri)
74 | {
75 | $this->printTaskInfo('URI: ' . $uri . '');
76 | $this->option('-l', $uri);
77 |
78 | return $this;
79 | }
80 |
81 | public function siteAlias($alias)
82 | {
83 | $this->printTaskInfo('Site Alias: ' . $alias . '');
84 | $this->siteAlias = $alias;
85 |
86 | return $this;
87 | }
88 |
89 | public function debug()
90 | {
91 | $this->option('-d');
92 |
93 | return $this;
94 | }
95 |
96 | public function verbose()
97 | {
98 | $this->option('-v');
99 |
100 | return $this;
101 | }
102 |
103 | public function simulate()
104 | {
105 | $this->option('-s');
106 |
107 | return $this;
108 | }
109 |
110 | public function siteName($siteName)
111 | {
112 | $this->argForNextCommand('--site-name=' . escapeshellarg($siteName));
113 |
114 | return $this;
115 | }
116 |
117 | /**
118 | * Add an argument used in the next invocation of drush.
119 | *
120 | * @param string $arg
121 | *
122 | * @return $this
123 | */
124 | protected function argForNextCommand($arg)
125 | {
126 | return $this->argsForNextCommand($arg);
127 | }
128 |
129 | /**
130 | * Add multiple arguments used in the next invocation of drush.
131 | *
132 | * @param array|string $args can also be multiple parameters
133 | *
134 | * @return $this
135 | */
136 | protected function argsForNextCommand($args)
137 | {
138 | if (!is_array($args)) {
139 | $args = func_get_args();
140 | }
141 | $this->argumentsForNextCommand .= ' ' . implode(' ', $args);
142 |
143 | return $this;
144 | }
145 |
146 | public function siteMail($siteMail)
147 | {
148 | $this->argForNextCommand('--site-mail=' . $siteMail);
149 |
150 | return $this;
151 | }
152 |
153 | public function sitesSubdir($sitesSubdir)
154 | {
155 | $this->argForNextCommand('--sites-subdir=' . $sitesSubdir);
156 |
157 | return $this;
158 | }
159 |
160 | public function locale($locale)
161 | {
162 | $this->argForNextCommand('--locale=' . $locale);
163 |
164 | return $this;
165 | }
166 |
167 | public function accountMail($accountMail)
168 | {
169 | $this->argForNextCommand('--account-mail=' . $accountMail);
170 |
171 | return $this;
172 | }
173 |
174 | public function accountName($accountName)
175 | {
176 | $this->argForNextCommand('--account-name=' . escapeshellarg($accountName));
177 |
178 | return $this;
179 | }
180 |
181 | public function accountPass($accountPass)
182 | {
183 | $this->argForNextCommand('--account-pass=' . escapeshellarg($accountPass));
184 |
185 | return $this;
186 | }
187 |
188 | public function dbPrefix($dbPrefix)
189 | {
190 | $this->argForNextCommand('--db-prefix=' . $dbPrefix);
191 |
192 | return $this;
193 | }
194 |
195 | public function dbSu($dbSu)
196 | {
197 | $this->argForNextCommand('--db-su=' . $dbSu);
198 |
199 | return $this;
200 | }
201 |
202 | public function dbSuPw($dbSuPw)
203 | {
204 | $this->argForNextCommand('--db-su-pw=' . escapeshellarg($dbSuPw));
205 |
206 | return $this;
207 | }
208 |
209 | public function sqliteDbUrl($relativePath)
210 | {
211 | return $this->dbUrl('sqlite://' . $relativePath);
212 | }
213 |
214 | public function dbUrl($dbUrl)
215 | {
216 | $this->argForNextCommand('--db-url=' . escapeshellarg($dbUrl));
217 |
218 | return $this;
219 | }
220 |
221 | public function mysqlDbUrl($dsn)
222 | {
223 | return $this->dbUrl('mysql://' . $dsn);
224 | }
225 |
226 | public function disableUpdateStatusModule()
227 | {
228 | $this->argForNextCommand('install_configure_form.update_status_module=0');
229 |
230 | return $this;
231 | }
232 |
233 | public function configDir($configDir)
234 | {
235 | $this->argForNextCommand('--config-dir=' . $configDir);
236 |
237 | return $this;
238 | }
239 |
240 | public function existingConfig($existingConfig = true)
241 | {
242 | if ($existingConfig) {
243 | $this->argForNextCommand('--existing-config');
244 | }
245 |
246 | return $this;
247 | }
248 |
249 | /**
250 | * Executes `drush status`
251 | *
252 | * @return $this
253 | */
254 | public function status()
255 | {
256 | return $this->drush('status');
257 | }
258 |
259 | /**
260 | * Runs the given drush command.
261 | *
262 | * @param string $command
263 | * @param bool $assumeYes
264 | *
265 | * @return $this
266 | */
267 | public function drush($command, $assumeYes = true)
268 | {
269 | if (is_array($command)) {
270 | $command = implode(' ', array_filter($command));
271 | }
272 |
273 | return $this->exec($this->injectArguments($command, $assumeYes));
274 | }
275 |
276 | /**
277 | * Prepends site-alias and appends arguments to the command.
278 | *
279 | * @param string $command
280 | * @param bool $assumeYes
281 | *
282 | * @return string the modified command string
283 | */
284 | protected function injectArguments($command, $assumeYes)
285 | {
286 | $cmd =
287 | $this->siteAlias . ' '
288 | . $command
289 | . ($assumeYes ? ' -y': '')
290 | . $this->arguments
291 | . $this->argumentsForNextCommand;
292 | $this->argumentsForNextCommand = '';
293 |
294 | return $cmd;
295 | }
296 |
297 | /**
298 | * Runs pending database updates.
299 | *
300 | * @return $this
301 | */
302 | public function updateDb()
303 | {
304 | $this->printTaskInfo('Do database updates');
305 | $this->drush('updb');
306 | $drushVersion = $this->getVersion();
307 | if (-1 === version_compare($drushVersion, '6.0')) {
308 | $this->printTaskInfo('Will clear cache after db updates for drush '
309 | . $drushVersion);
310 | $this->clearCache();
311 | } else {
312 | $this->printTaskInfo('Will not clear cache after db updates, since drush '
313 | . $drushVersion . ' should do it automatically');
314 | }
315 |
316 | return $this;
317 | }
318 |
319 | /**
320 | * Returns the drush version.
321 | *
322 | * @return string
323 | */
324 | public function getVersion()
325 | {
326 | if (empty($this->drushVersion)) {
327 | $isPrinted = $this->isPrinted;
328 | $this->isPrinted = false;
329 | $result = $this->executeCommand($this->executable . ' version');
330 | $output = $result->getMessage();
331 | $this->drushVersion = 'unknown';
332 | if (preg_match('#[0-9.]+#', $output, $matches)) {
333 | $this->drushVersion = $matches[0];
334 | }
335 | $this->isPrinted = $isPrinted;
336 | }
337 |
338 | return $this->drushVersion;
339 | }
340 |
341 | /**
342 | * Clears the given cache.
343 | *
344 | * @param string $name cache name
345 | *
346 | * @return $this
347 | */
348 | public function clearCache($name = 'all')
349 | {
350 | $this->printTaskInfo('Clear cache');
351 |
352 | return $this->drush('cc ' . $name);
353 | }
354 |
355 | /**
356 | * @param bool $force force revert even if Features assumes components' state are default
357 | * @param string $excludedFeatures space-delimited list of features to exclude from being reverted
358 | *
359 | * @return $this
360 | */
361 | public function revertAllFeatures($force = false, $excludedFeatures = '')
362 | {
363 | $this->printTaskInfo('Revert all features');
364 | $args = $excludedFeatures . ($force ? ' --force' : '');
365 |
366 | return $this->drush('fra ' . $args);
367 | }
368 |
369 | /**
370 | * Enables the maintenance mode.
371 | *
372 | * @return $this
373 | */
374 | public function maintenanceOn()
375 | {
376 | $this->printTaskInfo('Turn maintenance mode on');
377 |
378 | return $this->drush('vset --exact maintenance_mode 1');
379 | }
380 |
381 | /**
382 | * Disables the maintenance mode.
383 | *
384 | * @return $this
385 | */
386 | public function maintenanceOff()
387 | {
388 | $this->printTaskInfo('Turn maintenance mode off');
389 |
390 | return $this->drush('vdel --exact maintenance_mode');
391 | }
392 |
393 | /**
394 | * @param string $installationProfile
395 | *
396 | * @return $this
397 | */
398 | public function siteInstall($installationProfile)
399 | {
400 | return $this->drush('site-install ' . $installationProfile);
401 | }
402 | }
403 |
--------------------------------------------------------------------------------
/src/loadTasks.php:
--------------------------------------------------------------------------------
1 | task(DrushStack::class, $pathToDrush);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/tests/DrushStackTest.php:
--------------------------------------------------------------------------------
1 | setContainer($container);
31 |
32 | // Prepare temp directory.
33 | $this->fs = new Filesystem();
34 | $this->tmpDir = realpath(sys_get_temp_dir()) . DIRECTORY_SEPARATOR . 'robo-drush';
35 | }
36 |
37 | // Scaffold the collection builder
38 | public function collectionBuilder()
39 | {
40 | $emptyRobofile = new \Robo\Tasks;
41 |
42 | return $this->getContainer()->get('collectionBuilder', [$emptyRobofile]);
43 | }
44 |
45 | public function testYesIsAssumed()
46 | {
47 | $command = $this->taskDrushStack()
48 | ->drush('command')
49 | ->getCommand();
50 | $this->assertEquals('drush command -y', $command);
51 | }
52 |
53 | public function testAbsenceofYes()
54 | {
55 | $command = $this->taskDrushStack()
56 | ->drush('command', false)
57 | ->getCommand();
58 | $this->assertEquals('drush command', $command);
59 | }
60 |
61 | public function testOptionsArePrependedBeforeEachCommand()
62 | {
63 | $command = $this->taskDrushStack()
64 | ->drupalRootDirectory('/var/www/html/app')
65 | ->drush('command-1')
66 | ->drush('command-2')
67 | ->getCommand();
68 | $this->assertEquals(2, preg_match_all('#-r /var/www/html/app#', $command));
69 | }
70 |
71 | public function testSiteInstallCommand()
72 | {
73 | $pw = 'p"|&w';
74 | $command = $this->taskDrushStack()
75 | ->siteName('Site Name')
76 | ->siteMail('site-mail@example.com')
77 | ->locale('de')
78 | ->accountMail('mail@example.com')
79 | ->accountName('admin')
80 | ->accountPass($pw)
81 | ->dbPrefix('drupal_')
82 | ->dbSu('su_account')
83 | ->dbSuPw($pw)
84 | ->sqliteDbUrl('sit"es/default/.ht.sqlite')
85 | ->disableUpdateStatusModule()
86 | ->siteInstall('minimal')
87 | ->getCommand();
88 | $expected = 'drush site-install minimal -y --site-name=' . escapeshellarg('Site Name')
89 | . ' --site-mail=site-mail@example.com'
90 | . ' --locale=de --account-mail=mail@example.com --account-name=' . escapeshellarg('admin')
91 | . ' --account-pass=' . escapeshellarg($pw)
92 | . ' --db-prefix=drupal_ --db-su=su_account --db-su-pw=' . escapeshellarg($pw) . ' --db-url=' . escapeshellarg('sqlite://sit"es/default/.ht.sqlite')
93 | . ' install_configure_form.update_status_module=0';
94 | $this->assertEquals($expected, $command);
95 | }
96 |
97 | public function testExistingConfigDefaultsToTrue()
98 | {
99 | $command = $this->taskDrushStack()
100 | ->existingConfig()
101 | ->siteInstall('minimal')
102 | ->getCommand();
103 | $expected = 'drush site-install minimal -y --existing-config';
104 | $this->assertEquals($expected, $command);
105 | }
106 |
107 | /**
108 | * @dataProvider existingConfigWithBooleanParamIsRespectedProvider
109 | *
110 | * @param mixed $existingConfigParam
111 | * @param string $commandParam
112 | */
113 | public function testExistingConfigWithBooleanParamIsRespected(
114 | $existingConfigParam,
115 | $commandParam = ' --existing-config'
116 | ) {
117 | $command = $this->taskDrushStack()
118 | ->existingConfig($existingConfigParam)
119 | ->siteInstall('minimal')
120 | ->getCommand();
121 | $expected = 'drush site-install minimal -y' . $commandParam;
122 | $this->assertEquals($expected, $command);
123 | }
124 |
125 | public function existingConfigWithBooleanParamIsRespectedProvider()
126 | {
127 | return [
128 | // trueish
129 | 'true' => [true],
130 | '1' => [1],
131 | '"1"' => ['1'],
132 | // falsish
133 | 'false' => [false, ''],
134 | '0' => [0, ''],
135 | '"0"' => ['0', ''],
136 | 'null' => [null, ''],
137 | 'empty string' => ['', ''],
138 | ];
139 | }
140 |
141 | public function testSiteAliasIsFirstOption()
142 | {
143 | $command = $this->taskDrushStack()
144 | ->drupalRootDirectory('/var/www/html/app')
145 | ->siteAlias('@qa')
146 | ->drush('command-1')
147 | ->drush('command-2')
148 | ->getCommand();
149 | $this->assertEquals(2, preg_match_all('#drush @qa comm#', $command));
150 | }
151 |
152 | public function testDrushStatus()
153 | {
154 | $result = $this->taskDrushStack(__DIR__ . '/../vendor/bin/drush')
155 | ->printed(false)
156 | ->status()
157 | ->run();
158 | $this->assertTrue($result->wasSuccessful(), 'Exit code was: ' . $result->getExitCode());
159 | }
160 |
161 | /**
162 | * @dataProvider drushVersionProvider
163 | *
164 | * @param string $composerDrushVersion version to require with composer (can be different e.g. for RC versions)
165 | * @param string $expectedVersion version to compare
166 | */
167 | public function testDrushVersion($composerDrushVersion, $expectedVersion = null)
168 | {
169 | if (null === $expectedVersion) {
170 | $expectedVersion = $composerDrushVersion;
171 | }
172 | if (version_compare('5.6', phpversion()) > 0 && version_compare($expectedVersion, '9.0') > 0) {
173 | $this->markTestSkipped(phpversion() . ' too low for drush ' . $expectedVersion);
174 | }
175 |
176 | $cwd = getcwd();
177 | $this->ensureDirectoryExistsAndClear($this->tmpDir);
178 | chdir($this->tmpDir);
179 | $this->writeComposerJSON();
180 | $this->composer('require --no-progress --no-suggest --update-with-dependencies drush/drush:"' . $composerDrushVersion . '"');
181 | $actualVersion = $this->taskDrushStack($this->tmpDir . '/vendor/bin/drush')
182 | ->getVersion();
183 | $this->assertEquals($expectedVersion, $actualVersion);
184 | chdir($cwd);
185 | }
186 |
187 | /**
188 | * Should return an array of arrays with the following values:
189 | * 0: $composerDrushVersion (can be different e.g. for RC versions)
190 | * 1: $expectedVersion
191 | *
192 | * @return array
193 | */
194 | public function drushVersionProvider()
195 | {
196 | return [
197 | '8' => ['8.1.15'],
198 | '9-rc1' => ['9.0.0-rc1', '9.0.0'],
199 | '9' => ['9.4.0'],
200 | ];
201 | }
202 |
203 | /**
204 | * Writes the default composer json to the temp directory.
205 | */
206 | protected function writeComposerJSON()
207 | {
208 | $json = json_encode($this->composerJSONDefaults(), JSON_PRETTY_PRINT);
209 | file_put_contents($this->tmpDir . '/composer.json', $json);
210 | }
211 |
212 | /**
213 | * Provides the default composer.json data.
214 | *
215 | * @return array
216 | */
217 | protected function composerJSONDefaults()
218 | {
219 | return array(
220 | 'minimum-stability' => 'beta'
221 | );
222 | }
223 |
224 | /**
225 | * Wrapper for the composer command.
226 | *
227 | * @param string $command composer command name, arguments and/or options
228 | *
229 | * @throws RuntimeException
230 | */
231 | protected function composer($command)
232 | {
233 | exec(escapeshellcmd('composer -q ' . $command), $output, $exitCode);
234 | if ($exitCode !== 0) {
235 | throw new \RuntimeException('Composer returned a non-zero exit code.');
236 | }
237 | }
238 |
239 | /**
240 | * Makes sure the given directory exists and has no content.
241 | *
242 | * @param string $directory
243 | */
244 | protected function ensureDirectoryExistsAndClear($directory)
245 | {
246 | if (is_dir($directory)) {
247 | $this->fs->remove($directory);
248 | }
249 | $this->fs->mkdir($directory, 0777);
250 | }
251 | }
252 |
--------------------------------------------------------------------------------